iosswifthere-apiheremapsheremaps-ios-sdk

Why is the zoom level for Here iOS Explore not changing in the code below? In fact the camera is zooming in on the map after the zoomTo() func


The initial zoom value and final zoom value are 16.8... I checked them. I found something possibly relevant in the documentation for Here Explore:

Any method that modifies the state of the camera will be enqueued and the state will only be updated after drawing the next frame. https://developer.here.com/documentation/ios-sdk-explore/4.11.2.0/api_reference/Classes/MapCamera.html Could this note be related to this situation?

import heresdk
import UIKit

class ViewController: UIViewController {
   
    

    var mapView : MapView!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Initialize MapView without a storyboard.
        mapView = MapView(frame: view.bounds)
        view.addSubview(mapView)

        // Load the map scene using a map scheme to render the map with.
        mapView.mapScene.loadScene(mapScheme: MapScheme.normalDay, completion: onLoadScene)
    }

    
    
   
    
    
    // Completion handler when loading a map scene.
    private func onLoadScene(mapError: MapError?) {
        guard mapError == nil else {
            print("Error: Map scene not loaded, \(String(describing: mapError))")
            return
        }

        // Configure the map.
        let camera = mapView.camera
                
//                mapView.mapScene.setLayerVisibility(layerName: MapScene.Layers.landmarks, visibility: VisibilityState.visible)
                
        
        let coordinates = [GeoCoordinates(latitude: 51, longitude: 10),
                               GeoCoordinates(latitude: 49, longitude: 13.3946),
                               GeoCoordinates(latitude: 52.53894, longitude: 13.39194),
                               GeoCoordinates(latitude: 52.54014, longitude: 13.37958)]

        if let box =  GeoBox.containing(geoCoordinates: coordinates) {

            
            var cameraUpdate = MapCameraUpdateFactory.lookAt(area: box)
      
            camera.applyUpdate(cameraUpdate)

            var zoomLevel = camera.state.zoomLevel
           
           //zoom level must decrease here according to me but it actually increases  
            camera.zoomTo(zoomLevel: zoomLevel - 3)
           
            var finalzoom = camera.state.zoomLevel
            
            let geoPolyline = try! GeoPolyline(vertices: coordinates)
                let lineColor = UIColor(red: 0, green: 0.56, blue: 0.54, alpha: 0.63)
                let mapPolyline = MapPolyline(geometry: geoPolyline,
                                              widthInPixels: 30,
                                              color: lineColor)
            mapView.mapScene.addMapPolyline(mapPolyline)

        }
        
        
        
    }
    

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        mapView.handleLowMemory()
    }
}

Solution

  • Your observation is correct. Camera calls can be enqueued, but will only take effect after the next frame.

    In your case, you try to change the zoom twice.

    1. camera.applyUpdate(cameraUpdate) // This zooms quite far away to encompass the set box.
    2. camera.zoomTo(zoomLevel: zoomLevel - 3) // This is not executed based on the result of 1) as it takes the current state: camera.state.zoomLevel

    So, basically, your second change of the zoom level is:

    var zoomLevel = camera.state.zoomLevel // This is still default zoom level.
    camera.zoomTo(zoomLevel: zoomLevel - 3)
    

    As a result your new zoom level will be 16. The enqueued box update from step 1) is overwritten by your code.

    What you are trying to do is to await the outcome of the box zoom level change, take the resulting zoom level and decrease it by 3. This is something you cannot enqueue, as you would have to wait for the next frame to complete.

    It is only possible to wait until the MapIdleListener has been completed and the first zoom operation is done. Then you can take the resulting new zoom level and substract 3 - or, better, you can try an alternative approach:

            // Zoom to the box and add a padding of 100 pixels.
            let orientation = GeoOrientationUpdate(bearing: camera.state.orientationAtTarget.bearing,
                                                   tilt: camera.state.orientationAtTarget.tilt)
            let origin = Point2D(x: 100, y: 100)
            let sizeInPixels = Size2D(width: mapView.viewportSize.width - 200, height: mapView.viewportSize.height - 200)
            let mapViewportWithPadding = Rectangle2D(origin: origin, size: sizeInPixels)
            let cameraUpdate = MapCameraUpdateFactory.lookAt(area: box,
                                                             orientation: orientation,
                                                             viewRectangle: mapViewportWithPadding)
            camera.applyUpdate(cameraUpdate)
    
            let geoPolyline = try! GeoPolyline(vertices: coordinates)
            let lineColor = UIColor(red: 0, green: 0.56, blue: 0.54, alpha: 0.63)
            let mapPolyline = MapPolyline(geometry: geoPolyline,
                                          widthInPixels: 30,
                                          color: lineColor)
            mapView.mapScene.addMapPolyline(mapPolyline)
    

    Here you do not need to wait for the resulting zoom level and you can zoom to the box with some additional padding - which will also decrease the zoom level, but with a more consistent and predictable outcome.