1

what i am trying to achieve is this, when the userMarker be inside the visible bounds accomplish some actions, for that this is my code.

let screenWidth: Float = Float((map.frame.size.width))
let screenHeight: Float = Float((map.frame.size.height))
let minScreenPos: NTScreenPos = NTScreenPos(x: 0.0, y: 0.0)
let maxScreenPos: NTScreenPos = NTScreenPos(x: screenWidth, y:screenHeight)

let minPosWGS = projection.fromWgs84(map.screen(toMap: minScreenPos))!
let maxPosWGS = projection.fromWgs84(map.screen(toMap: maxScreenPos))!

let mapBounds = NTMapBounds(min: minPosWGS, max: maxPosWGS)
let markerCenter = projection.fromWgs84(userMarker.getBounds().getCenter())
let markerBounds = userMarker.getBounds()

let containPos = mapBounds!.contains(markerCenter)
let containBounds = mapBounds!.contains(markerBounds)

print(containPos)
print(containBounds)

But always the output is false, what i am doing wrong, any help, please.

Randy Hector
  • 89
  • 1
  • 1
  • 9

2 Answers2

1

Alright, there are several things here....

Firstly, when are you doing your screenToMap calculation? It will return 0 when your mapView hasn't fully rendered yet (even if your mapView already has a frame).

So you definitely cannot do it in our viewDidLoad or viewWillAppear, but, currently, also not after layoutSubviews. You need to calculate it after your map has rendered, this can be achieved using mapRenderer's onMapRendered event.

Example available here: https://github.com/CartoDB/mobile-ios-samples/blob/master/AdvancedMap.Objective-C/AdvancedMap/CaptureController.mm

We created an issue concerning this: https://github.com/CartoDB/mobile-sdk/issues/162

Secondly, if you ask for coordinates from CartoMobileSDK's method, coordinates are already returned in our internal coordinate system, meaning that you don't need to do any additional conversion. The correct way to ask for bounds and position would be:

let minPosWGS = map.screen(toMap: minScreenPos)!
let maxPosWGS = map.screen(toMap: maxScreenPos)!

and:

let markerCenter = userMarker!.getBounds().getCenter()

Thirdly, X increases from left to right on your screen, as well as on your map, however, Y increases from top to bottom on your screen, but from bottom to top on your map, so you'd have to initialize min and max as such:

let screenWidth = Float(map.frame.size.width)
let screenHeight = Float(map.frame.size.height)
let minScreenPos = NTScreenPos(x: 0.0, y: screenHeight)
let maxScreenPos = NTScreenPos(x: screenWidth, y: 0)

Please note that this calculation also depends on your view's orientation and map rotation. Currently we assume that your rotation is 0 and your view is in portrait mode.

And finally, iOS uses scaled coordinates, but Carto's Mobile SDK expects true coordinates. So you need to multiply your values by scale:

let screenWidth = Float(map.frame.size.width *  UIScreen.main.scale)
let screenHeight = Float(map.frame.size.height *  UIScreen.main.scale)
Nikitah
  • 719
  • 5
  • 15
  • thanks for your suggestions i post the answer i found before your post, please if you have time take a look at it and tell me your suggestions :) – Randy Hector Nov 28 '17 at 17:13
0

Hi @Nikitah i end up with this solution

i implement onMapMoved event from MapEventsListener an there i ask for this

if latestLocation != nil {
    delegate?.hideLocationButton()
}

So in mi hideLocationButton method i do this

let screenWidth: Float = Float(map.frame.width) * 2
let screenHeight: Float = Float(map.frame.height) * 2

let minScreenPos: NTScreenPos = NTScreenPos(x: 0, y: 0)
let maxScreenPos: NTScreenPos = NTScreenPos(x: screenWidth, y: screenHeight)
let screenBounds = NTScreenBounds(min: minScreenPos, max: maxScreenPos)

let contain = screenBounds?.contains(map.map(toScreen: marker.getBounds().getCenter()))

I realise that it was better ask for the position and then convert that NTMapPos in NTScreenPos, and ask if that screen pos was inside the the actual screen bounds.

In the finally suggestion you said that i need to multiply by the scale so i supouse that where i multiply the screenWidht and screenHeight by two this will be the screen scale?, i did that bacause the map width&height in console outpout was the half of the iphone screen so i improvise :), will be better to use UIScreen.main.scale

About the third suggestion i will try it and post back.

Randy Hector
  • 89
  • 1
  • 1
  • 9
  • If your solution works better for you, great. However, yeah, you should still check how it works with different orientations and rotations. And you should definitely use `UIScreen.main.scale`, your current device/simulator's scale may be 2, but that's not the case for all devices . – Nikitah Nov 29 '17 at 08:00
  • Hi, i test it in all rotations and orientations and i get the spected behavior, also using `UIScreen.main.scale` – Randy Hector Dec 01 '17 at 16:22