Powered by Zoomin Software. For more details please contactZoomin

HERE SDK for iOS (Navigate Edition) - Developer Guide

Product category
Technology
Doc type
Version
Product lifecycle
This publication

HERE SDK for iOS (Navigate Edition) - Developer Guide: Examples and use cases

Table of Contents

Examples and use cases

Explore practical examples and use cases to effectively utilize indoor maps and venues with the HERE SDK. This section covers a range of topics to help you get the most out of our indoor mapping capabilities.

List all indoor maps

The HERE SDK for iOS (Navigate Edition) allows you to list all private venues that are accessible for your account and the selected collection. VenueMap contains a list which holds VenueInfo elements containing venue Identifier, venue ID and venue Name.

let venueInfo:[VenueInfo]? = venueEngine?.venueMap.getVenueInfoList()
if let venueInfo = venueInfo {
  for venueInfo in venueInfo {
      print("Venue Identifier: \(venueInfo.venueIdentifier)." + " Venue Id: \(venueInfo.venueId)." + " Venue Name: \(venueInfo.venueName).")
  }
}

For maps with venue identifier as UUID, venueId would return 0.

Load and show a venue

The HERE SDK for iOS (Navigate Edition) allows you to load and visualize venues by identifier. You must know the venue's identifier for the current set of credentials. There are several ways to load and visualize the venues.

A VenueMap has two methods to add a venue to the map: selectVenueAsync() and addVenueAsync(). Both methods use getVenueService().addVenueToLoad() to load the venue by Identifier and then add it to the map. The method selectVenueAsync() also selects the venue:

venueEngine.venueMap.selectVenueAsync(venueIdentifier: String);
venueEngine.venueMap.addVenueAsync(venueIdentifier: String);

Note

For legacy maps with an int based venue ID, VenueMap still supports selectVenueAsync(venueID: Int) and addVenueAsync(venueID: Int) to load the venue by venue ID.

Once the venue is loaded, the VenueService calls the VenueDelegate.onGetVenueCompleted() method:

// Delegate for the venue loading event.
extension ViewController: VenueDelegate {
    func onGetVenueCompleted(venueIdentifier: String, venueModel: VenueModel?, online: Bool, venueStyle: VenueStyle?) {
        if venueModel == nil {
            print("Loading of venue \(venueIdentifier) failed!")
        }
    }
}

Note

For legacy maps with an int based venue ID, VenueService calls the VenueListener.onGetVenueCompleted(venueID: Int, venueModel: VenueModel?, online: Bool, venueStyle: VenueStyle?) method.

Once the venue is loaded successfully, if you are using the addVenueAsync() method, only the VenueLifecycleDelegate.onVenueAdded() method will be triggered. If you are using the selectVenueAsync()method, the VenueSelectionDelegate.onSelectedVenueChanged() method will also be triggered.

// Delegate for the venue selection event.
extension ViewController: VenueSelectionDelegate {
    func onSelectedVenueChanged(deselectedVenue: Venue?, selectedVenue: Venue?) {
        if let venueModel = selectedVenue?.venueModel {
            if moveToVenue {
                // Move camera to the selected venue.
                let center = GeoCoordinates(latitude: venueModel.center.latitude,
                                            longitude: venueModel.center.longitude,
                                            altitude: 500.0)
                mapView.camera.lookAt(point: center)
                // 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?.isTopologyVisible = true;
            }
        }
    }
}

A Venue can also be removed from the VenueMap, which triggers the VenueLifecycleDelegate.onVenueRemoved(venueIdentifier: String) method:

venueEngine.venueMap.removeVenue(venue: venue)

Note

For legacy maps with an int based venue ID, if you are using the addVenueAsync() method, the VenueLifecycleListener.onVenueAdded() method will be triggered. When removing an int based venue ID from VenueMap, the VenueLifecycleListener.onVenueRemoved(venueID: Int) is triggered.

Label text preference

You can override the default label text preference for a venue.

Once the VenueEngine is initialized, a callback is called. From this point on, there is access to the VenueService. The optional method setLabeltextPreference() can be called to set the label text preference during rendering. Overriding the default style label text preference provides an opportunity to set the following options as a list where the order defines the preference:

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

These can be set in any desired order. For example, if the label text preference does not contain "OCCUPANT_NAMES" then it will switch to "SPACE_NAME" and so on, based on the order of the list. Nothing is displayed if no preference is found.

private func onVenueEngineInit() {
    // Get VenueService and VenueMap objects.
    let venueMap = venueEngine.venueMap
    let venueService = venueEngine.venueService

    // Add needed delegates.
    venueService.addServiceDelegate(self)
    venueService.addVenueDelegate(self)
    venueMap.addVenueSelectionDelegate(self)

    // Start VenueEngine. Once authentication is done, the authentication completion handler
    // will be triggered. Afterwards VenueEngine will start VenueService. Once VenueService
    // is initialized, VenueServiceListener.onInitializationCompleted method will be called.
    venueEngine.start(callback: {
        error, data in if let error = error {
            print("Failed to authenticate, reason: " + error.localizedDescription)
        }
    })

    if (hrn != "") {
        // Set platform catalog HRN
        venueService.setHrn(hrn: hrn)
    }

    // Set label text preference
    venueService.setLabeltextPreference(labelTextPref: LabelPref)
}

Select venue drawings and levels

A Venue object allows you to control the state of the venue.

The property Venue.selectedDrawing allows you to get and set a drawing which is visible on the map. When a new drawing is selected, the VenueDrawingSelectionDelegate.onDrawingSelected() method is triggered.

The following provides an example of how to select a drawing when an item is clicked in a UITableView:

extension DrawingSwitcher: UITableViewDelegate {
    public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let drawingIndex: Int = indexPath.row
        if let venue = venueMap?.selectedVenue {
            // Set the selected drawing when a user clicks on the item in the table view.
            let drawing: VenueDrawing = venue.venueModel.drawings[drawingIndex]
            venue.selectedDrawing = drawing
            ...
        }
    }
}

The properties Venue.selectedLevel, Venue.selectedLevelIndex and Venue.selectedLevelZIndex allow you to get and set a level which will be visible on the map. If a new level is selected, the VenueLevelSelectionDelegate.onLevelSelected() method is triggered.

The following provides an example of how to select a level based on a reversed levels list from UITableView:

extension LevelSwitcher: UITableViewDelegate {
    public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // Rows in the LevelSwitcher's table view are presented in the reversed way
        currentLevelIndex = Int32(levels.count - indexPath.row - 1)
        updateLevel(currentLevelIndex)
    }
}
func updateLevel(_ levelIndex: Int32) {
    if let venue = venueMap?.selectedVenue {
        venue.selectedLevelIndex = currentLevelIndex
    }
}

A full example of the UI switchers to control drawings and levels is available in the "IndoorMap" example app, available on GitHub.

Customize the style of a venue

You can change the visual style of VenueGeometry objects. Geometry style and/or label style objects must be created and provided to the Venue.setCustomStyle() method:

// Create geometry and label styles for the selected geometry.
geometryStyle = VenueGeometryStyle(
    mainColor: selectedColor, outlineColor: selectedOutlineColor, outlineWidth: 1)
labelStyle = VenueLabelStyle(
    fillColor: selectedTextColor, outlineColor: selectedTextOutlineColor, outlineWidth: 1, maxFont: 28)
venue.setCustomStyle(geometries: [geometry], style: geometryStyle, labelStyle: labelStyle)

Select space by identifier

The ID of spaces, levels and drawings can be extracted using getIdentifier(), e.g. for spaces call: spaces.getIdentifier(). Then, for using those id values, a specific space can be searched in a level or a drawing with getGeometryById(id:).

var geometriesID : [String] = [];
var geometries : [VenueGeometry] = [];
for id in geometriesID
{
    VenueGeometry geometry = selectedVenue?.getSelectedDrawing().getGeometryById(id);
    geometries.append(geometry);
}
geometryStyle = VenueGeometryStyle(
    mainColor: selectedColor, outlineColor: selectedOutlineColor, outlineWidth: 1)
labelStyle = VenueLabelStyle(
    fillColor: selectedTextColor, outlineColor: selectedTextOutlineColor, outlineWidth: 1, maxFont: 28)
selectedVenue.setCustomStyle(geometries: geometries, style: geometryStyle, labelStyle: labelStyle)

Handle tap gestures on a venue

You can select a venue object by tapping it. First, set the tap delegate:

// Create a venue tap handler and set it as default tap delegate.
mapView.gestures.tapDelegate = VenueTapHandler(venueEngine: venueEngine,
                                               mapView: mapView,
                                               geometryLabel: geometryNameLabel)

Inside the tap delegate, you can use the tapped geographic coordinates as parameter for the VenueMap.getGeometry() and VenueMap.getVenue() methods:

public func onTap(origin: Point2D) {
    deselectGeometry()

    let venueMap = venueEngine.venueMap
    // Get geo coordinates of the tapped point.
    if let position = mapView.viewToGeoCoordinates(viewCoordinates: origin) {
        // If the tap point was inside a selected venue, try to pick a geometry inside.
        // Otherwise try to select an another venue, if the tap point was on top of one of them.
        if let selectedVenue = venueMap.selectedVenue, let geometry = venueMap.getGeometry(position: position) {
            onGeometryPicked(venue: selectedVenue, geometry: geometry)
        } else if let venue = venueMap.getVenue(position: position) {
            venueMap.selectedVenue = venue
        }
    }
}

func deselectGeometry() {
    // If a map marker is already on the screen, remove it.
    if let currentMarker = marker {
        mapView.mapScene.removeMapMarker(currentMarker)
    }
}

func onGeometryPicked(venue: Venue,
                      geometry: VenueGeometry) {
    // If the geomtry has an icon, add a map marker on top of the geometry.
    if geometry.lookupType == .icon {
        if let image = getMarkerImage() {
            marker = MapMarker(at: geometry.center,
                               image: image,
                               anchor: Anchor2D(horizontal: 0.5, vertical: 1.0))
            if let marker = marker {
                mapView.mapScene.addMapMarker(marker)
            }
        }
    }
}

HERE recommends that you deselect the tapped geometry when the selected venue, drawing, or level has changed:

public init(venueEngine: VenueEngine, mapView: MapView, geometryLabel: UILabel) {
    ...
    let venueMap = venueEngine.venueMap
    venueMap.addVenueSelectionDelegate(self)
    venueMap.addDrawingSelectionDelegate(self)
    venueMap.addLevelSelectionDelegate(self)
}

deinit {
    let venueMap = venueEngine.venueMap
    venueMap.removeVenueSelectionDelegate(self)
    venueMap.removeDrawingSelectionDelegate(self)
    venueMap.removeLevelSelectionDelegate(self)
}
extension VenueTapHandler: VenueSelectionDelegate {
    public func onSelectedVenueChanged(deselectedVenue: Venue?, selectedVenue: Venue?) {
        self.deselectGeometry()
    }
}

extension VenueTapHandler: VenueDrawingSelectionDelegate {
    public func onDrawingSelected(venue: Venue, deselectedDrawing: VenueDrawing?, selectedDrawing: VenueDrawing) {
        self.deselectGeometry()
    }
}

extension VenueTapHandler: VenueLevelSelectionDelegate {
    public func onLevelSelected(venue: Venue, drawing: VenueDrawing, deselectedLevel: VenueLevel?, selectedLevel: VenueLevel) {
        self.deselectGeometry()
    }
}

A full example showing usage of the map tap event with venues is available in the "IndoorMap" example app, available on GitHub.

Was this article helpful?
TitleResults for “How to create a CRG?”Also Available inAlert