ガイド変更履歴HERE SDK API references
ガイド

例とユースケース

屋内地図は、Navigateライセンスでのみ使用できます。

HERE SDKを使用して、屋内地図と施設を効果的に活用するための実用的な例とユースケースを確認してください。このセクションでは、屋内地図機能を最大限に活用するためのさまざまなトピックを取り上げます。

すべての屋内地図を一覧表示する

HERE SDK for Android (Navigate) を使用すると、アカウントと選択したコレクションでアクセス可能なすべての民間施設を一覧表示できます。VenueMapには、施設識別子、施設ID、施設名を含むVenueInfo要素を保持するリストが含まれます。

List<VenueInfo> venueInfo = venueEngine.getVenueMap().getVenueInfoList();
for (int i = 0; i< venueInfo.size(); i++) {
    Log.d(TAG, "Venue Identifier: " + venueInfo.get(i).getVenueIdentifier() + " Venue Id: "+venueInfo.get(i).getVenueId() + " Venue Name: "+venueInfo.get(i).getVenueName());
}

施設IDがUUIDの地図の場合、getVenueId()は0を返します。

施設を読み込んで表示する

HERE SDK for Android (Navigate) を使用すると、Identifierごとに施設を読み込んで視覚化できます。現在の資格情報セットの施設IDを知っている必要があります。施設を読み込んで視覚化する方法は複数あります。

VenueMapには、マップに施設を追加する2つのメソッド、selectVenueAsync()addVenueAsync()があります。どちらのメソッドでも、getVenueService().addVenueToLoad()を使用してIdentifierで施設を読み込み、それをマップに追加します。メソッドselectVenueAsync()では施設も選択します。

venueEngine.getVenueMap().selectVenueAsync(String venueIdentifier);
venueEngine.getVenueMap().addVenueAsync(String venueIdentifier);

int型の施設IDを使用するレガシーマップの場合、VenueMapは引き続きselectVenueAsync(int venueID)およびaddVenueAsync(int venueID)をサポートしており、施設IDで施設を読み込みます。

施設が読み込まれると、VenueServiceVenueMapListener.onGetVenueCompleted()メソッドを呼び出します。

// Listener for the venue loading event
private final VenueMapListener venueMapListener = (venueIdentifier, venueModel, online, venueStyle) -> {
    if (venueModel == null) {
        Log.e(TAG, "Failed to load the venue: " + venueIdentifier);
    }
};

int型の施設IDを使用するレガシーマップの場合、VenueServiceVenueListener.onGetVenueCompleted(venueID, venueModel, online, venueStyle)メソッドを呼び出します。

施設が正常に読み込まれると、addVenueAsync()メソッドを使用している場合は、VenueMapLifecycleListener.onVenueAdded()メソッドのみがトリガーされます。selectVenueAsync() メソッドを使用している場合は、VenueSelectionListener.onSelectedVenueChanged() メソッドもトリガーされます。

// Listener for the venue selection event.
private final VenueSelectionListener venueSelectionListener =
    (deselectedVenue, selectedVenue) -> {
        if (selectedVenue != null) {
            // Move camera to the selected venue.
            GeoCoordinates venueCenter = selectedVenue.getVenueModel().getCenter();
            final double distanceInMeters = 500;
            MapMeasure mapMeasureZoom = new MapMeasure(MapMeasure.Kind.DISTANCE_IN_METERS, distanceInMeters);
            mapView.getCamera().lookAt(
                    new GeoCoordinates(venueCenter.latitude, venueCenter.longitude),
                    mapMeasureZoom);
            // This functions is used to facilitate the toggling of topology visibility.
            // Setting isTopologyVisible property to true will render the topology on scene and false will lead to hide the topology.
            selectedVenue.setTopologyVisible(true);
        }
    };

VenueVenueMapから削除することもでき、これによりVenueMapLifecycleListener.onVenueRemoved(venueIdentifier)メソッドがトリガーされます。

venueEngine.getVenueMap().removeVenue(venue);

int型の施設IDを使用するレガシーマップの場合、addVenueAsync()メソッドを使用するとVenueLifecycleListener.onVenueAdded()メソッドがトリガーされます。
int型の施設IDをVenueMapから削除すると、VenueLifecycleListener.onVenueRemoved(venueID)がトリガーされます。

ラベルテキストの優先設定

施設のデフォルトのラベル テキスト設定を上書きできます。

VenueEngineが初期化されると、コールバックが呼び出されます。この時点から、VenueService にアクセスできるようになります。オプションのメソッド setLabeltextPreference() を呼び出して、レンダリング中にラベル テキストの設定を行うことができます。デフォルトのスタイル ラベル テキスト優先設定をオーバーライドすると、順序によって優先設定が定義されるリストとして次のオプションを設定できます。

  • "OCCUPANT_NAMES"
  • "SPACE_NAME"
  • "INTERNAL_ADDRESS"
  • "SPACE_TYPE_NAME"
  • "SPACE_CATEGORY_NAME"

これらは任意の順序で設定できます。たとえば、ラベル テキストの優先設定に "OCCUPANT_NAMES" が含まれない場合は、リストの順序に基づいて "SPACE_NAME" などに切り替わります。優先設定が見つからない場合は何も表示されません。

private void onVenueEngineInitCompleted() {
    // Get VenueService and VenueMap objects.
    VenueService service = venueEngine.getVenueService();
    VenueMap venueMap = venueEngine.getVenueMap();

    // Add needed listeners.
    service.add(serviceListener);
    service.add(venueListener);
    venueMap.add(venueSelectionListener);

    // Start VenueEngine. Once authentication is done, the authentication callback
    // will be triggered. After, VenueEngine will start VenueService. Once VenueService
    // is initialized, VenueServiceListener.onInitializationCompleted method will be called.
    venueEngine.start((authenticationError, authenticationData) -> {
        if (authenticationError != null) {
            Log.e(TAG, "Failed to authenticate, reason: " + authenticationError.value);
        }
    });

    if(HRN != "") {
        // Set platform catalog HRN
        service.setHrn(HRN);
    }

    // Set label text preference
    service.setLabeltextPreference(LabelPref);
}

施設の図面と階を選択する

Venue オブジェクトを使用すると、施設の状態を制御できます。

メソッド getSelectedDrawing()setSelectedDrawing() を使用すると、地図上に表示される描画を取得および設定できます。新しい描画が選択されると、VenueDrawingSelectionListener.onDrawingSelected() メソッドがトリガーされます。

以下に、ListView でアイテムをクリックしたときに描画を選択する方法の例を示します。

@Override
public void onItemClick(AdapterView<?> parent, final View view, int position, long id) {
    VenueModel venueModel = venue.getVenueModel();
    // Set the selected drawing when a user clicks on the item in the list.
    venue.setSelectedDrawing(venueModel.getDrawings().get(position));
}

メソッド getSelectedLevelIndex() および setSelectedLevelIndex() を使用すると、レベルのリスト内の位置に基づいてレベルを取得および設定できます。新しいレベルが選択されると、VenueLevelSelectionListener.onLevelSelected() メソッドがトリガーされます。

以下は、ListViewの反転レベルリストに基づいてレベルを選択する方法の例を示しています。

listView.setOnItemClickListener((parent, view, position, id) -> {
    if (venueMap.getSelectedVenue() != null) {
        // Revers an index, as levels in LevelSwitcher appear in a different order
        venueMap.getSelectedVenue().setSelectedLevelIndex(maxLevelIndex - position);
    }
});

描画とレベルを制御するUIスイッチャーの完全な例は、GitHubにある「IndoorMap」サンプルアプリで入手できます。

施設のスタイルをカスタマイズする

VenueGeometry オブジェクトのビジュアル スタイルを変更できます。ジオメトリー スタイル オブジェクトやラベル スタイル オブジェクトを作成して、Venue.setCustomStyle() メソッドに提供する必要があります。

private final VenueGeometryStyle geometryStyle = new VenueGeometryStyle(
        SELECTED_COLOR, SELECTED_OUTLINE_COLOR, 1);
private final VenueLabelStyle labelStyle = new VenueLabelStyle(
        SELECTED_TEXT_COLOR, SELECTED_TEXT_OUTLINE_COLOR, 1, 28);
ArrayList<VenueGeometry> geometries =
        new ArrayList<>(Collections.singletonList(geometry));
venue.setCustomStyle(geometries, geometryStyle, labelStyle);

識別子でスペースを選択する

スペース、レベル、描画の ID は getIdentifier() を使用して抽出できます。スペースの場合は spaces.getIdentifier() を呼び出します。次に、これらの ID 値を使用して、getGeometryById(String id) でレベルや描画の特定のスペースを検索します。

ArrayList<String> geometriesID;
ArrayList<VenueGeometry> geometries;
for(String id : geometriesID)
{
    VenueGeometry geometry = selectVenue.getSelectedDrawing().getGeometryById(id);
    geometries.add(geometry);
}
private final VenueGeometryStyle geometryStyle = new VenueGeometryStyle(
        SELECTED_COLOR, SELECTED_OUTLINE_COLOR, 1);
private final VenueLabelStyle labelStyle = new VenueLabelStyle(
        SELECTED_TEXT_COLOR, SELECTED_TEXT_OUTLINE_COLOR, 1, 28);
selectVenue.setCustomStyle(geometries, geometryStyle, labelStyle);

施設のタップ ジェスチャーを処理する

施設オブジェクトはタップで選択できます。まず、タップ リスナーを設定します。

mapView.getGestures().setTapListener(tapListener);

タップ リスナー内では、タップされた地理座標を VenueMap.getGeometry() メソッドと VenueMap.getVenue() メソッドのパラメーターとして使用できます。

private final TapListener tapListener = origin -> {
    deselectGeometry();

    // Get geo position of the tap.
    GeoCoordinates position = mapView.viewToGeoCoordinates(origin);
    if (position == null) {
        return;
    }

    VenueMap venueMap = venueEngine.getVenueMap();
    // Get VenueGeometry under the tapped position.
    VenueGeometry geometry = venueMap.getGeometry(position);

    if (geometry != null) {
        // If there is a geometry, put a marker on top of it.
        marker = new MapMarker(position, markerImage, new Anchor2D(0.5f, 1f));
        mapView.getMapScene().addMapMarker(marker);
    } else {
        // If no geometry was tapped, check if there is a not-selected venue under
        // the tapped position. If there is one, select it.
        Venue venue = venueMap.getVenue(position);
        if (venue != null) {
            venueMap.setSelectedVenue(venue);
        }
    }
};

private void deselectGeometry() {
    // If marker is already on the screen, remove it.
    if (marker != null) {
        mapView.getMapScene().removeMapMarker(marker);
    }
}

選択した施設、描画、またはレベルが変更された場合は、タップされたジオメトリーの選択を解除することをお勧めします。

private final VenueSelectionListener venueSelectionListener =
        (deselectedController, selectedController) -> deselectGeometry();

private final VenueDrawingSelectionListener drawingSelectionListener =
        (venue, deselectedController, selectedController) -> deselectGeometry();

private final VenueLevelSelectionListener levelChangeListener =
        (venue, drawing, oldLevel, newLevel) -> deselectGeometry();

void setVenueMap(VenueMap venueMap) {
    if (this.venueMap == venueMap) {
        return;
    }

    // Remove old venue map listeners.
    removeListeners();
    this.venueMap = venueMap;

    if (this.venueMap != null) {
        this.venueMap.add(venueSelectionListener);
        this.venueMap.add(drawingSelectionListener);
        this.venueMap.add(levelChangeListener);
        deselectGeometry();
    }
}

private void removeListeners() {

    if (this.venueMap != null) {
        this.venueMap.remove(venueSelectionListener);
        this.venueMap.remove(drawingSelectionListener);
        this.venueMap.remove(levelChangeListener);
    }
}

施設でのマップタップイベントの使用法を示す完全な例は、GitHubにある「IndoorMap」サンプルアプリで入手できます。

屋内ルーティング

HERE SDK for Android (Navigate) は施設内のルートを計算し視覚化する包括的な屋内ルーティング機能を提供します。このセクションでは、屋内ルーティング機能の設定方法と使用方法について説明します。

屋内ルートの計算

屋内ルートを計算するには、IndoorRoutingEngineを作成し、施設およびフロア情報を含む経由地を指定する必要があります。経由地は出発地点と到着地点ごとに作成します。

まず、次のようにルーティングエンジンを作成します。

IndoorRoutingEngine routingEngine = new IndoorRoutingEngine(venueEngine.getVenueService());

開始地と目的地の経由地を作成します。屋内の場所には、次のように施設IDとフロアIDを指定します。

IndoorWaypoint startWaypoint = new IndoorWaypoint(
    position,
    String.valueOf(venueModel.getIdentifier()),
    String.valueOf(venue.getSelectedLevel().getIdentifier()));

IndoorWaypoint destinationWaypoint = new IndoorWaypoint(
    position,
    String.valueOf(venueModel.getIdentifier()),
    String.valueOf(venue.getSelectedLevel().getIdentifier()));

routingEngineを使用して次のようにルートを計算します。

IndoorRouteOptions routeOptions = new IndoorRouteOptions();
engine.calculateRoute(startWaypoint, destinationWaypoint, routeOptions, 
    (routingError, routeList) -> {
        if (routingError == null && routeList != null) {
            Route route = routeList.get(0);
            // Use the calculated route
        }
    });

複数のフロアにまたがるルートの計算

屋内ルートは、施設内の複数のフロアにまたがることがあります。SDKはフロア間の移動を自動的に処理し、ルート内のフロア変更に関する情報を提供します。

屋内セクションの詳細およびフロア情報にアクセスするには、次のようにします。

for (Section section : route.getSections()) {
    // Check if section has indoor details
    if (section.getIndoorSectionDetails() != null) {
        IndoorSectionDetails indoorDetails = section.getIndoorSectionDetails();
        Log.d(TAG, "Indoor Section - Departure: " + 
            indoorDetails.getDeparturePlace().venueId);
        Log.d(TAG, "Indoor Section - Arrival: " + 
            indoorDetails.getArrivalPlace().venueId);

        // Iterate through indoor maneuvers
        for (IndoorManeuver indoorManeuver : indoorDetails.getIndoorManeuvers()) {
            if (indoorManeuver.getAction() != null) {
                Log.d(TAG, "IndoorManeuver Action: " + indoorManeuver.getAction());
            }
            Log.d(TAG, "IndoorManeuver Location Info: Level_Z_Index: " + 
                indoorManeuver.getLevelZIndex());

            // Check for level change data
            if (indoorManeuver.getIndoorLevelChangeData() != null) {
                Log.d(TAG, "IndoorManeuver Level change using: " + 
                    indoorManeuver.getIndoorLevelChangeData().connector +
                    " changeInLevel: " + 
                    indoorManeuver.getIndoorLevelChangeData().deltaZ);
            }
        }
    }
}

IndoorLevelChangeDataは、次の情報を提供します。

  • connector:使用されるフロア間の接続手段の種類 (エレベーター、階段、エスカレーター、スロープなど)
  • deltaZ:フロアの変化量 (上方向は正、下方向は負)

ルート計算時のエラー

ルーティングコールバックでは、さまざまなエラーシナリオに対応するためにIndoorRoutingErrorパラメーターが提供されます。ルート計算中に発生した一部の問題はルート通知として報告され、その後IndoorRoutingErrorオブジェクトに変換されます。次の通知タイプがサポートされています。

  • NO_ROUTE_FOUND:選択した経由地間にルートが見つかりません
  • COULD_NOT_MATCH_ORIGIN:出発地を特定できません
  • COULD_NOT_MATCH_DESTINATION:目的地を特定できません

その他のエラーには、ネットワーク接続の問題、サービスエラー、リクエストの検証に関する問題があります。

engine.calculateRoute(startWaypoint, destinationWaypoint, routeOptions, 
    (routingError, routeList) -> {
        if (routingError == null && routeList != null) {
            Route route = routeList.get(0);
            // Process the route
        } else {
            String errorMsg;
            switch (routingError) {
                // Route notice errors - converted from route notices
                case NO_ROUTE_FOUND:
                    errorMsg = "No route found between selected waypoints";
                    break;
                case COULD_NOT_MATCH_ORIGIN:
                    errorMsg = "Origin could not be matched";
                    break;
                case COULD_NOT_MATCH_DESTINATION:
                    errorMsg = "Destination could not be matched";
                    break;
                case MAP_NOT_FOUND:
                    errorMsg = "Requested map not found";
                    break;
                case PARSING_ERROR:
                    errorMsg = "Routing response not in correct format";
                    break;
                case UNKNOWN_ERROR:
                default:
                    errorMsg = "Unknown error encountered";
                    break;
            }
            // Handle the error appropriately
            Log.e(TAG, errorMsg);
        }
    });

フロア間の接続手段の回避オプション

屋内ルートの計算時に、ユーザーの設定やアクセシビリティ要件に基づいて、特定の種類のフロア間の接続手段を回避するようルーティングエンジンを設定できます。

IndoorRouteOptions routeOptions = new IndoorRouteOptions();

// Add features to avoid
routeOptions.indoorAvoidanceOptions.indoorFeatures.add(
    IndoorLevelChangeFeatures.ELEVATOR);
routeOptions.indoorAvoidanceOptions.indoorFeatures.add(
    IndoorLevelChangeFeatures.ESCALATOR);
routeOptions.indoorAvoidanceOptions.indoorFeatures.add(
    IndoorLevelChangeFeatures.STAIRS);

回避可能なフロア間の接続手段の種類は次のとおりです。

  • ELEVATOR:エレベーター
  • ESCALATOR:エスカレーター
  • STAIRS:階段
  • RAMP:一般的なスロープ
  • PEDESTRIAN_RAMP:歩行者専用スロープ
  • DRIVE_RAMP:車両用スロープ
  • CAR_LIFT:車両用リフト
  • ELEVATOR_BANK:エレベーター群
  • CONNECTOR:汎用接続手段

回避オプションを削除するには、次のようにします。

routeOptions.indoorAvoidanceOptions.indoorFeatures.remove(
    IndoorLevelChangeFeatures.ELEVATOR);

ルート設定

IndoorRouteOptionsオブジェクトを使用して、ルート計算の設定を行います。

ルート最適化モード

次のように、最速ルートと最短ルートから選択します。

IndoorRouteOptions routeOptions = new IndoorRouteOptions();

// For fastest route
routeOptions.routeOptions.optimizationMode = OptimizationMode.FASTEST;

// For shortest route
routeOptions.routeOptions.optimizationMode = OptimizationMode.SHORTEST;

歩行者の歩行速度

歩行者ルートの歩行速度をカスタマイズできます。これは推定移動時間に影響します。速度はメートル/秒で指定し、有効範囲は0.5~2.0 m/sです。

IndoorRouteOptions routeOptions = new IndoorRouteOptions();

// Set walk speed (in meters per second)
// Valid range: 0.5 to 2.0 m/s
// Default is typically 1.0 m/s
routeOptions.speedInMetersPerSecond = 1.5;

検証の例は次のとおりです。

double speed = 1.2; // User input

// Validate and clamp the speed
if (speed < 0.5) {
    speed = 0.5;
} else if (speed > 2.0) {
    speed = 2.0;
}

routeOptions.speedInMetersPerSecond = speed;

ターン・バイ・ターンアクション

屋内ルートでは、IndoorManeuverクラスを通じて詳細なターン・バイ・ターンの誘導情報が提供されます。

for (Section section : route.getSections()) {
    if (section.getIndoorSectionDetails() != null) {
        IndoorSectionDetails indoorDetails = section.getIndoorSectionDetails();
        
        for (IndoorManeuver indoorManeuver : indoorDetails.getIndoorManeuvers()) {
            // Get the maneuver action
            if (indoorManeuver.getAction() != null) {
                Log.d(TAG, "Action: " + indoorManeuver.getAction());
            }
            
            // Get the level information
            Log.d(TAG, "Level Z-Index: " + indoorManeuver.getLevelZIndex());
            
            // Check for level change information
            if (indoorManeuver.getIndoorLevelChangeData() != null) {
                Log.d(TAG, "Level change via: " + 
                    indoorManeuver.getIndoorLevelChangeData().connector);
                Log.d(TAG, "Change in levels: " + 
                    indoorManeuver.getIndoorLevelChangeData().deltaZ);
            }
            
            // Get space information (room/area details)
            if (indoorManeuver.getIndoorSpaceData() != null) {
                Log.d(TAG, "Space Category: " + 
                    indoorManeuver.getIndoorSpaceData().spaceCategory);
                Log.d(TAG, "Space Type: " + 
                    indoorManeuver.getIndoorSpaceData().spaceType);
            }
        }
    }
}

IndoorManeuverは次を提供します。

  • Action:実行するアクションのタイプ
  • Level Z-Index:操作が行われるフロアの階層
  • Indoor Level Change Data:接続手段の種類や移動するフロア数など、フロア間の移動に関する情報
  • Indoor Space Data:進入または通過する空間に関する詳細 (カテゴリーやタイプなど)

ルートのETAと総距離

計算されたルートから、到着予測時刻 (ETA) と総距離を取得できます。

Route route = routeList.get(0);

// Get the total duration in seconds
long durationInSeconds = route.getDuration().getSeconds();

// Get the total length in meters
int lengthInMeters = route.getLengthInMeters();

// Format for display
Log.d(TAG, "Route duration: " + durationInSeconds + " seconds");
Log.d(TAG, "Route distance: " + lengthInMeters + " meters");

// Convert to more readable format
long minutes = durationInSeconds / 60;
long seconds = durationInSeconds % 60;
double kilometers = lengthInMeters / 1000.0;

Log.d(TAG, String.format("ETA: %d min %d sec", minutes, seconds));
Log.d(TAG, String.format("Distance: %.2f km", kilometers));

セクション単位の詳細は、次のとおりです。

for (Section section : route.getSections()) {
    long sectionDuration = section.getDuration().getSeconds();
    int sectionLength = section.getLengthInMeters();
    
    Log.d(TAG, "Section duration: " + sectionDuration + " seconds");
    Log.d(TAG, "Section distance: " + sectionLength + " meters");
}

ルートのレンダリング

IndoorRoutingControllerは、地図上での屋内ルートの視覚化を処理します。

まず、次のようにコントローラーを作成します。

IndoorRoutingController controller = new IndoorRoutingController(venueMap, mapView);

ポリラインのレンダリング

地図上にルートを表示するには、showRoute()メソッドを使用します。

// Create route style
IndoorRouteStyle routeStyle = new IndoorRouteStyle();

// Show the route
controller.showRoute(route, routeStyle);

ルートを非表示にするには、次のようにします。

controller.hideRoute();

フロア変更アイコンの配置

さまざまなルート要素やフロア変更インジケーターのカスタムマーカーを設定します。

IndoorRouteStyle routeStyle = new IndoorRouteStyle();

// Set start and destination markers
Anchor2D middleBottomAnchor = new Anchor2D(0.5, 1.0);
MapImage startImage = MapImageFactory.fromResource(
    context.getResources(), R.drawable.ic_route_start);
MapMarker startMarker = new MapMarker(
    new GeoCoordinates(0.0, 0.0), startImage, middleBottomAnchor);
routeStyle.setStartMarker(startMarker);

MapImage endImage = MapImageFactory.fromResource(
    context.getResources(), R.drawable.ic_route_end);
MapMarker endMarker = new MapMarker(
    new GeoCoordinates(0.0, 0.0), endImage, middleBottomAnchor);
routeStyle.setDestinationMarker(endMarker);

// Set transport mode markers
MapImage walkImage = MapImageFactory.fromResource(
    context.getResources(), R.drawable.indoor_walk);
MapMarker walkMarker = new MapMarker(
    new GeoCoordinates(0.0, 0.0), walkImage, new Anchor2D());
routeStyle.setWalkMarker(walkMarker);

MapImage driveImage = MapImageFactory.fromResource(
    context.getResources(), R.drawable.indoor_drive);
MapMarker driveMarker = new MapMarker(
    new GeoCoordinates(0.0, 0.0), driveImage, new Anchor2D());
routeStyle.setDriveMarker(driveMarker);

次のように、方向インジケーター付きのフロア変更フィーチャーのマーカーを設定します。

// Configure markers for each level change feature
IndoorLevelChangeFeatures[] features = new IndoorLevelChangeFeatures[] {
    IndoorLevelChangeFeatures.ELEVATOR,
    IndoorLevelChangeFeatures.ESCALATOR,
    IndoorLevelChangeFeatures.STAIRS,
    IndoorLevelChangeFeatures.RAMP
};

for (IndoorLevelChangeFeatures feature : features) {
    // Create markers for up, down, and neutral directions
    MapMarker upMarker = createMarkerForFeature(feature, 1);    // Going up
    MapMarker downMarker = createMarkerForFeature(feature, -1); // Going down
    MapMarker neutralMarker = createMarkerForFeature(feature, 0); // No vertical change
    
    routeStyle.setIndoorMarkersFor(feature, upMarker, downMarker, neutralMarker);
}

次のように、フィーチャータイプと方向に基づいてマーカーを作成するヘルパーメソッドを定義します。

private MapMarker createMarkerForFeature(IndoorLevelChangeFeatures feature, int deltaZ) {
    int resourceId = getResourceForFeature(feature, deltaZ);
    if (resourceId == 0) {
        return null;
    }
    
    MapImage image = MapImageFactory.fromResource(
        context.getResources(), resourceId);
    if (image != null) {
        return new MapMarker(new GeoCoordinates(0.0, 0.0), image, new Anchor2D());
    }
    return null;
}

private int getResourceForFeature(IndoorLevelChangeFeatures feature, int deltaZ) {
    switch (feature) {
        case ELEVATOR:
            if (deltaZ > 0) return R.drawable.indoor_elevator_up;
            if (deltaZ < 0) return R.drawable.indoor_elevator_down;
            return R.drawable.indoor_elevator;
        case ESCALATOR:
            if (deltaZ > 0) return R.drawable.indoor_escalator_up;
            if (deltaZ < 0) return R.drawable.indoor_escalator_down;
            return R.drawable.indoor_escalator;
        case STAIRS:
            if (deltaZ > 0) return R.drawable.indoor_stairs_up;
            if (deltaZ < 0) return R.drawable.indoor_stairs_down;
            return R.drawable.indoor_stairs;
        case RAMP:
            if (deltaZ > 0) return R.drawable.indoor_ramp_up;
            if (deltaZ < 0) return R.drawable.indoor_ramp_down;
            return R.drawable.indoor_ramp;
        default:
            return 0;
    }
}

deltaZパラメーターは次のように方向を示します。

  • 1 (正):上のフロアに移動
  • -1 (負):下のフロアに移動
  • 0:上下方向のフロア変更なし

showRoute()メソッドはルートのレンダリングに関してカスタマイズの範囲が限定されています。フロアに関する高度なカスタマイズを適用する場合は、ルートの各座標間に描画されるMapPolylineを使用します。「地図上にルートを表示する」を参照してください。

施設を含む屋内ルーティングの使用方法を示す完全な例は、GitHubにある「IndoorMap」サンプルアプリで確認できます。


EN 日本語

HERE documentation

Find answers to your product and technical questions

Documentation

What's new

Videos

EN 日本語

HERE ドキュメント

製品や技術に関する質問の答えを見つけましょう。より多くの内容と最新の情報については、英語版をご覧ください。

ドキュメント

ダイナミックマップ

動的コンテンツ関連のAPIをアプリやサービスに活用して、ドライバーが安全・快適かつ予定どおりに目的地へ到着できるよう支援します。

地図とデータ

世界中を走行する多数のマッピング車両から得られる最新の位置情報データを活用し、精度の高い地図やカスタムレイヤーを構築できます。

最新情報

動画

(function () { const input = document.querySelector('input[data-typeahead]'); if (!input) return; // Prevent the form from submitting/navigating input.closest('form')?.addEventListener('submit', e => e.preventDefault()); input.addEventListener('input', function () { const q = this.value.trim().toLowerCase(); document.querySelectorAll('.nav-group-name').forEach(group => { let anyVisible = false; group.querySelectorAll('.nav-group-task').forEach(task => { const text = task.textContent.trim().toLowerCase(); const show = !q || text.includes(q); task.style.display = show ? '' : 'none'; if (show) anyVisible = true; }); // Hide the whole group header if nothing matches group.style.display = anyVisible || !q ? '' : 'none'; }); }); })(); (function () { function onTokenClick(event) { var link = event.target.closest('.sdk-for-ios .item .token'); if (!link) return; event.preventDefault(); console.log('token clicked', link.textContent.trim()); var item = link.closest('.item'); if (!item) return; var content = item.querySelector('.height-container'); if (!content) { console.log('no .height-container found for item', item); return; } var isHidden = window.getComputedStyle(content).display === 'none'; content.style.display = isHidden ? 'block' : 'none'; link.classList.toggle('token-open', isHidden); var href = link.getAttribute('href'); if (href) { if (history.pushState) history.pushState({}, '', href); else location.hash = href; } } function openHashTarget() { var hash = window.location.hash.slice(1); if (!hash) return; var anchor = document.querySelector('.sdk-for-ios a[name="' + hash + '"]'); if (!anchor) return; var item = anchor.closest('.item'); if (!item) return; var link = item.querySelector('.token'); var content = item.querySelector('.height-container'); if (!link || !content) return; content.style.display = 'block'; link.classList.add('token-open'); } function init() { console.log('HERE SDK accordion init'); openHashTarget(); } document.removeEventListener('click', onTokenClick); document.addEventListener('click', onTokenClick); if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } window.addEventListener('hashchange', openHashTarget); window.addEventListener('pageLoad', init); })();