PDA

View Full Version : change in zoomLevelConfigurations only take effect after significant speed change



guidove
13.04.2016, 20:03
While in navigation I have "autoZoom" enabled by setting the zoomLevelConfigurations of the SKNavSettings Property. Autozoom works fine.
Now, I also want the user to change the zoom level manually, so I added zoom buttons.

Upon tapping the zoom button I change the SKNavigationSettings zoomLevelConfigurations and call SKRoutingService.sharedInstance().changeNavigation Settings(self.navSettings)

Also this works fine, but the map doesn't zoom in or out immediately after tapping a zoom button. It only changes after a significant (> 2km/hr) speed change was detected (this is at least what I found in my tests, could also be a significant location change, I don't know.).

What I'd like to achieve is that when the user taps one of the zoom buttons, he sees the map zoom in or zoom out immediately, regardless if he's not moving or moving. I tried simulating a significant speed change right after changing the navSettings zoomLevelConfiguration (see commented out lines in code), but so far unsuccessful.

Is there a way to have a change in the zoomLevelConfigurations have effect immediately, regardless of a speed change?

Thanks & Regards,
Guido

Here is the code:


var maxZoomLevel: Float = 19
var navSettings: SKNavigationsettings!
var locManager: CLLocationManager //necessary to enable background navigation in iOS9 (as I'm still on 2.5.0)

@IBAction func tappedZoomInButton(sender: AnyObject) {
dispatch_async(dispatch_get_main_queue()) {
self.maxZoomLevel = min(19, self.maxZoomLevel + 1)
self.setZoomLevel()
SKRoutingService.sharedInstance().changeNavigation Settings(self.navSettings)
// let curLocation = self.locManager.location!
// let simLocation = CLLocation(coordinate: curLocation.coordinate, altitude: curLocation.altitude, horizontalAccuracy: curLocation.horizontalAccuracy, verticalAccuracy: curLocation.verticalAccuracy, course: curLocation.course, speed: curLocation.speed + 3, timestamp: curLocation.timestamp)
// SKPositionerService.sharedInstance().positionerMod e = .PositionSimulation
// SKPositionerService.sharedInstance().reportGPSLoca tion(simLocation)
// SKPositionerService.sharedInstance().positionerMod e = .RealPositions
}

}

@IBAction func tappedZoomOutButton(sender: AnyObject) {
dispatch_async(dispatch_get_main_queue()) {
guard self.maxZoomLevel > 7 else { return }
self.maxZoomLevel = max(7, self.maxZoomLevel - 1)
self.setZoomLevel()
SKRoutingService.sharedInstance().changeNavigation Settings(self.navSettings)
// let curLocation = self.locManager.location!
// let simLocation = CLLocation(coordinate: curLocation.coordinate, altitude: curLocation.altitude, horizontalAccuracy: curLocation.horizontalAccuracy, verticalAccuracy: curLocation.verticalAccuracy, course: curLocation.course, speed: curLocation.speed + 3, timestamp: curLocation.timestamp)
// SKPositionerService.sharedInstance().positionerMod e = .PositionSimulation
// SKPositionerService.sharedInstance().reportGPSLoca tion(simLocation)
// SKPositionerService.sharedInstance().positionerMod e = .RealPositions
}
}

func setZoomLevel() {
let zoomLevel1 = SKZoomLevelConfiguration()
zoomLevel1.speedInterval = SKSpeedInterval(minimumSpeed: 0, maximumSpeed: 10)
zoomLevel1.zoomLevel = maxZoomLevel
let zoomLevel2 = SKZoomLevelConfiguration()
zoomLevel2.speedInterval = SKSpeedInterval(minimumSpeed: 10, maximumSpeed: 25)
zoomLevel2.zoomLevel = maxZoomLevel - 1
let zoomLevel3 = SKZoomLevelConfiguration()
zoomLevel3.speedInterval = SKSpeedInterval(minimumSpeed: 25, maximumSpeed: 70)
zoomLevel3.zoomLevel = maxZoomLevel - 2
let zoomLevel4 = SKZoomLevelConfiguration()
zoomLevel4.speedInterval = SKSpeedInterval(minimumSpeed: 70, maximumSpeed: 120)
zoomLevel4.zoomLevel = maxZoomLevel - 4
let zoomLevel5 = SKZoomLevelConfiguration()
zoomLevel5.speedInterval = SKSpeedInterval(minimumSpeed: 120, maximumSpeed: 500)
zoomLevel5.zoomLevel = maxZoomLevel - 6
navSettings.zoomLevelConfigurations = [zoomLevel1, zoomLevel2, zoomLevel3, zoomLevel4, zoomLevel5]
}

Adela_Silvia
18.04.2016, 16:29
The zoomLevelConfiguration is designed to properly work in navigation scenarios therefore it's connected to the movement speed (current implementation closely ties the zoomLevelConfiguration to the speed)
Maybe you can achieve your intended effect by manipulating the 3dCameraSettings?
See: http://developer.skobbler.com/docs/android/2.5.1/com/skobbler/ngx/map/SK3DCameraSettings.html

guidove
18.04.2016, 17:20
Thanks for the reply Adela.
I understand why it acts like it does. I guess the zoomLevelConfig is not meant to be changed during Navigation. I was just hoping there was a way to "trick" the framework to immediately apply the new zoomLevelConfiguration.

The 3DCameraSettings is not an option for me because I'm allowing the user to switch between 2D and 3D.

Is there no "trick" for the framework to apply the new zoomConfig immediately? I tried this by temporarily switching to "Simulation" mode and then sending a location that's different form the current location (see above commented out code), but that didn't seem to do the trick.

Thanks and regards,
Guido
Oh, I'm on iOS, still using 2.5.0 btw Perhaps I'm gonna update to 2.5.1, but depends on when your next release is planned. Any news on that? Saw the thread on this, but it's been quite there for a little while.

Adela_Silvia
19.04.2016, 15:42
Another trick: set zoomLevelConfig on nothing, force the zoom level you need (through visible region or something else) then set again the zoomLevelConfig - try this and let us know if this is a good solution for what you need.

Reg the new update - should be available soon (this/ next month)- until then we can offer the beta build for testing if you send a request at dev@telenav.com

guidove
20.04.2016, 19:32
Hi Adela,

Thanks for the suggestion. This actually seemed to work, however I ran into another issue: auto zoom is not working in 3D mode.
I decided to implement my own zooming function (see below) and ran into another problem: animateToZoomlevel and animateToBearing seem to reset the positionerAlignment of SKNavigationSettings. I tried setting back the positionerAlignment right after animating, but that didn't work. As a workaround for this I used visibleRegion and the (deprecated) bearing property of SKMapView. This is not as nice as these don't animate, but it does the trick.

Perhaps someone else is looking for the same so I'll share a bit of my code here. With this code you have autozoom and you can adjust the zoom level manually with zoomIn and zoomOut buttons. It works in 3D and 2D mode and in HeadingUp or NorthUp mode. It's just copy paste so if someone has questions about it, fire away.



@IBOutlet weak var zoomInButton: UIButton!
@IBOutlet weak var zoomOutButton: UIButton!
var maxZoomLevel: Float = 17
var zoomLevelsForSpeedRanges: [(minSpeedMperS: Double, zoomLevel: Float)]!
var currentSpeedRange: (minSpeedMperS: Double, maxSpeedMperS: Double) = (0,4)

func routingService(routingService: SKRoutingService!, didChangeCurrentSpeed speed: Double) {
//print("NAVDELEGATE: didChangeCurrentSpeed - \(speed)")
self.navInfo.currentSpeed = speed
maxSpeedMperS = max(maxSpeedMperS,speed)
if speed < currentSpeedRange.minSpeedMperS || speed >= currentSpeedRange.maxSpeedMperS {
self.zoomToNewZoomLevel()
}
if UIApplication.sharedApplication().applicationState == .Active {
dispatch_async(dispatch_get_main_queue()) {(_) -> Void in
self.updateSpeedLabel()
}
}
}

@IBAction func tappedZoomInButton(sender: AnyObject) {
dispatch_async(dispatch_get_main_queue()) {(_) -> Void in
self.mapSettingsVisibilityTimer?.invalidate()
self.mapSettingsVisibilityTimer = NSTimer.scheduledTimerWithTimeInterval(4, target: self, selector: #selector(NavViewController.hideMapSettingsView), userInfo: nil, repeats: false)
}
guard self.maxZoomLevel < 19 else { return }
self.maxZoomLevel = min(19, self.maxZoomLevel + 0.5)
self.setZoomLevelForRanges()
self.zoomToNewZoomLevel()
}

@IBAction func tappedZoomOutButton(sender: AnyObject) {
dispatch_async(dispatch_get_main_queue()) {(_) -> Void in
self.mapSettingsVisibilityTimer?.invalidate()
self.mapSettingsVisibilityTimer = NSTimer.scheduledTimerWithTimeInterval(4, target: self, selector: #selector(NavViewController.hideMapSettingsView), userInfo: nil, repeats: false)
}
guard self.maxZoomLevel > 7 else { return }
self.maxZoomLevel = max(7, self.maxZoomLevel - 0.5)
self.setZoomLevelForRanges()
self.zoomToNewZoomLevel()
}

@IBAction func tapped3DButton(sender: AnyObject) {
dispatch_async(dispatch_get_main_queue()) {
self.mapSettingsVisibilityTimer?.invalidate()
print("mapSettingsVisibilityTimer Timer Stopped")
self.mapSettingsVisibilityTimer = NSTimer.scheduledTimerWithTimeInterval(4, target: self, selector: #selector(NavViewController.hideMapSettingsView), userInfo: nil, repeats: false)
print("mapSettingsVisibilityTimer Timer Started")
}
if UD.mapIs2D! {
UD.mapIs2D = false
ThreeDButton.setImage(UIImage(named: "3D"), forState: .Normal)
SKRoutingService.sharedInstance().mapView?.setting s.displayMode = SKMapDisplayMode.Mode3D
}
else {
UD.mapIs2D = true
ThreeDButton.setImage(UIImage(named: "2D"), forState: .Normal)
SKRoutingService.sharedInstance().mapView?.setting s.displayMode = SKMapDisplayMode.Mode2D
}
zoomToNewZoomLevel()
}

@IBAction func tappedNorthUpButton(sender: AnyObject) {
dispatch_async(dispatch_get_main_queue()) {
self.mapSettingsVisibilityTimer?.invalidate()
print("mapSettingsVisibilityTimer Timer Stopped")
self.mapSettingsVisibilityTimer = NSTimer.scheduledTimerWithTimeInterval(4, target: self, selector: #selector(NavViewController.hideMapSettingsView), userInfo: nil, repeats: false)
print("mapSettingsVisibilityTimer Timer Started")
}
let currentZoomLevel = SKRoutingService.sharedInstance().mapView!.visible Region.zoomLevel
SKRoutingService.sharedInstance().mapView!.setting s.zoomLimits = SKMapZoomLimits(mapZoomLimitMin: currentZoomLevel, mapZoomLimitMax: currentZoomLevel)
if UD.mapNorthUp! {
UD.mapNorthUp = false
northUpButton.setImage(UIImage(named: "headingUp"), forState: .Normal)
if let currentBearing = SKPositionerService.sharedInstance().currentHeadin g?.trueHeading {
SKRoutingService.sharedInstance().mapView!.bearing = Float(currentBearing)
}
SKRoutingService.sharedInstance().mapView!.centerO nCurrentPosition()
SKRoutingService.sharedInstance().mapView!.setting s.headingMode = SKHeadingMode.Route
navSettings.positionerAlignment = SKPositionerAlignment(vertical: -0.25, horizontal: 0)
SKRoutingService.sharedInstance().changeNavigation Settings(navSettings)
}
else {
UD.mapNorthUp = true
northUpButton.setImage(UIImage(named: "northUp"), forState: .Normal)
SKRoutingService.sharedInstance().mapView!.setting s.headingMode = SKHeadingMode.RotatingHeading
navSettings.positionerAlignment = SKPositionerAlignment(vertical: -0.1, horizontal: 0)
SKRoutingService.sharedInstance().changeNavigation Settings(navSettings)
SKRoutingService.sharedInstance().mapView!.bearing = 0
}
SKRoutingService.sharedInstance().mapView!.setting s.zoomLimits = SKMapZoomLimits(mapZoomLimitMin: 0, mapZoomLimitMax: 19)
zoomToNewZoomLevel()
}

func setZoomLevelForRanges() {
zoomLevelsForSpeedRanges = [
(0, maxZoomLevel), // > 0 km/h
(4, maxZoomLevel - 1), // > 14,4 km/h
(9, maxZoomLevel - 2), // > 32,4 km/h
(25, maxZoomLevel - 3), // > 90 km/h
(40, maxZoomLevel - 3.5), // > 144 km/h
]
}

func zoomToNewZoomLevel() {
var newZoom: Float!
for (index, range) in zoomLevelsForSpeedRanges.enumerate().reverse() {
if navInfo.currentSpeed >= range.minSpeedMperS {
newZoom = range.zoomLevel
currentSpeedRange = (range.minSpeedMperS, index == 4 ? 500 : zoomLevelsForSpeedRanges[index+1].minSpeedMperS)
print("New Speed Range: \(currentSpeedRange.minSpeedMperS) - \(currentSpeedRange.maxSpeedMperS)")
break
}
}
dispatch_async(dispatch_get_main_queue()) {(_) -> Void in
SKRoutingService.sharedInstance().mapView.visibleR egion = SKCoordinateRegion(center: SKRoutingService.sharedInstance().mapView.visibleR egion.center, zoomLevel: newZoom)
}
}

Adela_Silvia
19.05.2016, 13:34
Happy to hear you manage to make it work and thanks for sharing with us the tricks.