【问题标题】:How to verify that a Map Position is inside the Map Bounds using carto-mobile SDK如何使用 carto-mobile SDK 验证地图位置是否在地图边界内
【发布时间】:2023-04-11 00:33:01
【问题描述】:

我想要实现的是,当 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)

但是输出总是错误的,我做错了什么,请帮忙。

【问题讨论】:

    标签: ios swift3 maps carto-mobile


    【解决方案1】:

    好吧,这里有几件事......

    首先,您什么时候进行screenToMap 计算?当您的 mapView 尚未完全渲染时(即使您的 mapView 已经有一个框架),它将返回 0。

    所以你绝对不能在我们的viewDidLoadviewWillAppear 中做到这一点,但目前在layoutSubviews 之后也不能这样做。您需要在地图渲染后计算它,这可以使用mapRendereronMapRendered 事件来实现。

    此处提供示例:https://github.com/CartoDB/mobile-ios-samples/blob/master/AdvancedMap.Objective-C/AdvancedMap/CaptureController.mm

    我们为此创建了一个问题:https://github.com/CartoDB/mobile-sdk/issues/162

    其次,如果你从CartoMobileSDK的方法中请求坐标,坐标已经返回到我们内部的坐标系中,也就是说你不需要做任何额外的转换。请求边界和位置的正确方法是:

    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 的移动 SDK 需要真实坐标。因此,您需要将值乘以比例:

    let screenWidth = Float(map.frame.size.width *  UIScreen.main.scale)
    let screenHeight = Float(map.frame.size.height *  UIScreen.main.scale)
    

    【讨论】:

    • 感谢您的建议,我在您的帖子之前发布了我找到的答案,如果您有时间请看一下并告诉我您的建议:)
    【解决方案2】:

    嗨@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()))
    

    我意识到最好先询问位置,然后在 NTScreenPos 中转换 NTMapPos,然后询问屏幕位置是否在实际屏幕边界内。

    在最后的建议中,您说我需要乘以比例,所以我认为我将 screenWidht 和 screenHeight 乘以 2 这将是屏幕比例?我这样做是因为控制台输出中的地图宽度和高度是iphone屏幕的一半,所以我即兴发挥:),使用 UIScreen.main.scale 会更好

    关于第三个建议,我会尝试并回复。

    【讨论】:

    • 如果您的解决方案更适合您,那就太好了。但是,是的,您仍然应该检查它如何在不同的方向和旋转下工作。而且您绝对应该使用UIScreen.main.scale,您当前的设备/模拟器的比例可能是2,但并非所有设备都是如此。
    • 嗨,我在所有旋转和方向上都对其进行了测试,我得到了预期的行为,也使用UIScreen.main.scale
    猜你喜欢
    • 1970-01-01
    • 2015-04-03
    • 1970-01-01
    • 1970-01-01
    • 2014-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-08
    相关资源
    最近更新 更多