如何使用 carto-mobile SDK 验证地图位置是否在地图边界内
How to verify that a Map Position is inside the Map Bounds using carto-mobile SDK
我想要实现的是,当 userMarker 在可见范围内完成一些操作时,这是我的代码。
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)
但总是输出错误,我做错了什么,请帮忙。
好吧,这里有几件事....
首先,你什么时候做你的screenToMap
计算?当您的 mapView
尚未完全呈现时,它将 return 0(即使您的 mapView 已经有一个框架)。
所以你在我们的 viewDidLoad
或 viewWillAppear
中肯定不能这样做,但是,目前,在 layoutSubviews
之后也不行。您需要在地图渲染后计算它,这可以使用 mapRenderer
的 onMapRendered
事件来实现。
我们创建了一个与此相关的问题:https://github.com/CartoDB/mobile-sdk/issues/162
其次,如果你从CartoMobileSDK的方法中请求坐标,坐标已经return在我们的内部坐标系中,这意味着你不需要做任何额外的转换。请求边界和位置的正确方法是:
let minPosWGS = map.screen(toMap: minScreenPos)!
let maxPosWGS = map.screen(toMap: maxScreenPos)!
和:
let markerCenter = userMarker!.getBounds().getCenter()
第三,X
在您的屏幕和地图上从左到右 增加,但是, Y
在屏幕上 从上到下 增加,但在地图上 从下到上 增加,所以你必须初始化最小值和最大值:
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)
请注意,此计算还取决于您的视图方向和地图旋转。目前我们假设您的旋转度为 0 并且您的视图处于纵向模式。
最后、iOS使用缩放坐标,但Carto的Mobile SDK需要真实坐标。所以你需要将你的值乘以比例:
let screenWidth = Float(map.frame.size.width * UIScreen.main.scale)
let screenHeight = Float(map.frame.size.height * UIScreen.main.scale)
嗨@Nikitah 我最终得到了这个解决方案
我从 MapEventsListener 实现 onMapMoved 事件,我在那里要求这个
if latestLocation != nil {
delegate?.hideLocationButton()
}
所以在 mi hideLocationButton 方法中我这样做
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()))
我意识到最好询问位置,然后将 NTMapPos 转换为 NTScreenPos,并询问该屏幕位置是否在实际屏幕边界内。
在最后的建议中你说我需要乘以比例所以我假设我将 screenWidht 和 screenHeight 乘以 2 这将是屏幕比例?我这样做是因为控制台输出中的地图宽度和高度是 iphone 屏幕的一半,所以我即兴创作:),使用 UIScreen.main.scale
会更好
关于第三个建议,我会尝试一下,然后 post 回来。
我想要实现的是,当 userMarker 在可见范围内完成一些操作时,这是我的代码。
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)
但总是输出错误,我做错了什么,请帮忙。
好吧,这里有几件事....
首先,你什么时候做你的screenToMap
计算?当您的 mapView
尚未完全呈现时,它将 return 0(即使您的 mapView 已经有一个框架)。
所以你在我们的 viewDidLoad
或 viewWillAppear
中肯定不能这样做,但是,目前,在 layoutSubviews
之后也不行。您需要在地图渲染后计算它,这可以使用 mapRenderer
的 onMapRendered
事件来实现。
我们创建了一个与此相关的问题:https://github.com/CartoDB/mobile-sdk/issues/162
其次,如果你从CartoMobileSDK的方法中请求坐标,坐标已经return在我们的内部坐标系中,这意味着你不需要做任何额外的转换。请求边界和位置的正确方法是:
let minPosWGS = map.screen(toMap: minScreenPos)!
let maxPosWGS = map.screen(toMap: maxScreenPos)!
和:
let markerCenter = userMarker!.getBounds().getCenter()
第三,X
在您的屏幕和地图上从左到右 增加,但是, Y
在屏幕上 从上到下 增加,但在地图上 从下到上 增加,所以你必须初始化最小值和最大值:
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)
请注意,此计算还取决于您的视图方向和地图旋转。目前我们假设您的旋转度为 0 并且您的视图处于纵向模式。
最后、iOS使用缩放坐标,但Carto的Mobile SDK需要真实坐标。所以你需要将你的值乘以比例:
let screenWidth = Float(map.frame.size.width * UIScreen.main.scale)
let screenHeight = Float(map.frame.size.height * UIScreen.main.scale)
嗨@Nikitah 我最终得到了这个解决方案
我从 MapEventsListener 实现 onMapMoved 事件,我在那里要求这个
if latestLocation != nil {
delegate?.hideLocationButton()
}
所以在 mi hideLocationButton 方法中我这样做
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()))
我意识到最好询问位置,然后将 NTMapPos 转换为 NTScreenPos,并询问该屏幕位置是否在实际屏幕边界内。
在最后的建议中你说我需要乘以比例所以我假设我将 screenWidht 和 screenHeight 乘以 2 这将是屏幕比例?我这样做是因为控制台输出中的地图宽度和高度是 iphone 屏幕的一半,所以我即兴创作:),使用 UIScreen.main.scale
会更好关于第三个建议,我会尝试一下,然后 post 回来。