MKMapView MKCircle 渲染半径太大的圆

2023-11-23

我面临着 MKCircle 外观的奇怪行为。基本上我试图画一个半径为 8500 公里、任意中心的圆。这是我的代码:

private func addCircle() {
    mapView.removeOverlays(mapView.overlays)
    let circle = MKCircle(centerCoordinate: mapCenter, radius: 8500000.0)
    mapView.addOverlay(circle)
}

我还有一个自定义的双击手势处理程序,它会覆盖地图视图的标准手势处理程序,并允许通过双击地图视图来更改地图中心:

private func configureGestureRecognizer() {
    doubleTapGestureRecognizer.addTarget(self, action: Selector("handleDoubleTap:"))
    doubleTapGestureRecognizer.numberOfTapsRequired = 2
    if let subview = mapView.subviews.first as? UIView {
        subview.addGestureRecognizer(doubleTapGestureRecognizer)
    }
    else {
        println("Can't add a gesture recognizer")
    }
}

@objc private func handleDoubleTap(sender: UITapGestureRecognizer) {
    let point = sender.locationInView(mapView)
    let location = mapView.convertPoint(point, toCoordinateFromView: mapView)
    mapCenter = location
    addCircles()
}

结果很奇怪:

Center in New York City

Center in far north from NYC

您可能会注意到这两个半径之间存在显着差异:第二个半径比第一个半径大得多!

发生了什么事以及如何使它们正确显示?

EDIT

感谢@blacksquare,我可以更接近解决方案,但仍然有北极的问题:

enter image description here

(小圆圈代表一个中心)


根据苹果的文档MKCircle:“随着纬度值远离赤道并向两极移动,地图点之间的物理距离变得更小。这意味着需要更多的地图点来表示相同的距离。因此,圆形叠加层的边界矩形变得随着该圆的中心点远离赤道并向两极移动,该圆就变大。”

正如安娜和沃伦都提到的,这不是一个错误——这是预期的行为。然而,文档之间似乎存在差异boundingMapRect and radius。该文档表明半径是距中心点的米数,这显然不是您的示例中的情况。

我认为这里发生的事情是,Apple 可能从来没有想过 MKCircle 会以您现在使用的规模使用。MKCircle创建一个 2D 圆,它不能既是圆又是投影图上圆形区域的精确表示。

现在,如果您只想创建一个不扭曲的均匀圆,并且其半径相对于其在赤道处的长度,则可以将圆在赤道处的长度设置为基半径,然后计算当前点的半径如下:

let baseCoord = CLLocationCoordinate2D(latitude: 0, longitude: 0)
let radius: Double = 850000.0

override func viewDidLoad() {
    super.viewDidLoad()
    mapView.region = MKCoordinateRegion(
        center: baseCoord,
        span: MKCoordinateSpan(
            latitudeDelta: 90,
            longitudeDelta: 180
        )
    )
    mapCenter = baseCoord
    let circle = MKCircle(centerCoordinate: mapCenter, radius: radius)
    baseRadius = circle.boundingMapRect.size.height / 2

    mapView.delegate = self
    configureGestureRecognizer()
}

private func addCircle() {

    mapView.removeOverlays(mapView.overlays)
    let circle = MKCircle(centerCoordinate: mapCenter, radius: radius)

    var currentRadius = circle.boundingMapRect.size.height / 2
    let factor = baseRadius / currentRadius
    var updatedRadius = factor * radius

    let circleToDraw = MKCircle(centerCoordinate: mapCenter, radius: updatedRadius)
    mapView.addOverlay(circleToDraw)
}

但如果您的计划是准确覆盖点击后 x 米内的所有空间,那就有点棘手了。首先,您将在双击操作中获取单击坐标,然后将其用作多边形的中心。

@objc private func handleDoubleTap(sender: UITapGestureRecognizer) {
    let point = sender.locationInView(mapView)
    currentCoord = mapView.convertPoint(point, toCoordinateFromView: mapView)
    mapCenter = currentCoord
    addPolygon()
}

In addPolygon,获取坐标并设置叠加层:

private func addPolygon() {
    var mapCoords = getCoordinates()
    mapView.removeOverlays(mapView.overlays)

    let polygon = MKPolygon(coordinates: &mapCoords, count: mapCoords.count)
    mapView.addOverlay(polygon)
}

给定一个点、方位角和角距离(坐标之间的距离除以地球半径),您可以使用以下公式计算另一个坐标的位置。一定要导入Darwin这样您就可以访问三角函数库

let globalRadius: Double = 6371000
let π = M_PI

private func getCoordinates() -> [CLLocationCoordinate2D] {
    var coordinates = [CLLocationCoordinate2D]()

    let lat1: Double = (currentCoord!.latitude)
    let long1: Double = (currentCoord!.longitude) + 180
    let factor = 30

    if let a = annotation {
        mapView.removeAnnotation(annotation)
    }

    annotation = MKPointAnnotation()
    annotation!.setCoordinate(currentCoord!)
    annotation!.title = String(format: "%1.2f°, %1.2f°", lat1, long1)
    mapView.addAnnotation(annotation)

    var φ1: Double = lat1 * (π / 180)
    var λ1: Double = long1 * (π / 180)
    var angularDistance =  radius / globalRadius

    var metersToNorthPole: Double = 0
    var metersToSouthPole: Double = 0

    for i in Int(lat1)..<89 {
        metersToNorthPole = metersToNorthPole + 111132.92 - (559.82 * cos(2 * φ1)) + (1.175 * cos(4 * φ1))
    }

    for var i = lat1; i > -89; --i {
        metersToSouthPole = metersToSouthPole + 111132.92 - (559.82 * cos(2 * φ1)) + (1.175 * cos(4 * φ1))
    }

    var startingBearing = -180
    var endingBearing = 180

    if metersToNorthPole - radius <= 0 {
        endingBearing = 0
        startingBearing = -360
    }

    for var i = startingBearing; i <= endingBearing; i += factor {

        var bearing = Double(i)

        var bearingInRadians: Double = bearing * (π / 180)

        var φ2: Double = asin(sin(φ1) * cos(angularDistance)
            + cos(φ1) * sin(angularDistance)
            * cos(bearingInRadians)
        )

        var λ2 = atan2(
            sin(bearingInRadians) * sin(angularDistance) * cos(φ1),
            cos(angularDistance) - sin(φ1) * sin(φ2)
        ) + λ1

        var lat2 = φ2 * (180 / π)
        var long2 = ( ((λ2 % (2 * π)) - π)) * (180.0 / π)

        if long2 < -180 {
            long2 = 180 + (long2 % 180)
        }

        if i == startingBearing && metersToNorthPole - radius <= 0 {
            coordinates.append(CLLocationCoordinate2D(latitude: 90, longitude: long2))
        } else if i == startingBearing && metersToSouthPole - radius <= 0 {
            coordinates.append(CLLocationCoordinate2D(latitude: -90, longitude: long2))
        }

        coordinates.append(CLLocationCoordinate2D(latitude: lat2, longitude: long2))
    }

    if metersToNorthPole - radius <= 0 {
        coordinates.append(CLLocationCoordinate2D(latitude: 90, longitude: coordinates[coordinates.count - 1].longitude))
    } else if metersToSouthPole - radius <= 0 {
        coordinates.append(CLLocationCoordinate2D(latitude: -90, longitude: coordinates[coordinates.count - 1].longitude))
    }

    return coordinates
}

In getCoordinates我们将度数转换为弧度,然后在半径大于到北极或南极的距离的情况下添加更多锚定坐标。

以下是半径分别为 8500 公里和 850 公里的极点附近曲线的几个示例:

enter image description here enter image description here

这是最终输出的示例,带有附加内容MKGeodesicPolyline覆盖(测地线表示球面上可能的最短曲线),显示了曲线的实际构建方式:

enter image description here

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MKMapView MKCircle 渲染半径太大的圆 的相关文章

  • Swift - 我可能已经删除了 Apple Swift Packages 集合

    我对 swift 和 XCode 很陌生 昨天我正在开发一个项目 想尝试一下某人制作的自定义日期选择器 所以我转到 添加包 并粘贴 GitHub 链接并添加它 我已经在我的项目中添加了一个名为 KeychainAccess 的不同包 方式
  • 在phonegap中播放本地声音

    我有一个 wav文件在我的www文件夹 我正在使用 jQuery 和以下代码 警报响起 但声音不播放 难道我做错了什么
  • 命令行工具中的框架问题

    在每个人开始向我扔其他堆栈溢出和论坛帖子之前 我把它们都看了 他们都没有帮忙 我有一个简单的 cmd 工具 名为swizzler并想要嵌入SwizzleSrc其中的框架 我已经遵循了所有教程并且堆栈溢出但没有运气 这就是我得到的 Build
  • 为什么我需要 2 个或更多核心数据模型?

    我很想知道谁使用多个核心数据模型以及为什么 有什么好处 我正在开发一个应用程序 我认为我可以从多个模型中受益 但我不确定其他好处 我即将推出的应用程序将适用于 iPad 和 iPhone 的另一个版本 iPad 有 3 个主要内容 iPho
  • iOS8 自签名证书已安装但仍不受信任

    由于我无法控制的原因 我需要使用自签名证书针对平台进行 iOS 开发 它是一个在 SAN 中具有特定 IP 地址的根证书 当证书安装在 OSX 系统帐户下时 所有浏览器现在将正常信任对给定 IP 地址的任何访问 通过电子邮件将同一证书发送到
  • 将时间舍入到最接近的三十秒

    我有一个应用程序 它显示每 30 秒过期的数据 准确地说 在 h m s 11 30 00 11 30 30 11 31 00 等 我可以获得当前时间 但我不确定如何计算现在到最近的三十秒之间的时间 我发现的所有内容都是 Objective
  • 如何使用 SwiftUI 使按钮可拖动/可移动?

    我正在尝试使用 SwiftUI 制作一个可移动的按钮 从看起来这应该可行 我尝试将带有文本的按钮放入另一个 ZStack 中 有一秒钟它可以工作 但一旦我释放按钮 拖动就会停止 我无法再拖动 我注意到尽管按钮已经移动 但水龙头仍然位于中心
  • iOS9 Swift 文件使用 NSURL 创建 NSFileManager.createDirectoryAtPath

    在iOS9之前 我们创建了一个像这样的目录 let documentsPath NSSearchPathForDirectoriesInDomains DocumentDirectory UserDomainMask true 0 as S
  • iOS UITableView:使用 CAGradientLayer 将背景颜色指定为渐变

    我刚刚开始使用 Xcode 4 3 中的主从视图模板 我试图更改主视图的背景颜色并将其设置为颜色渐变 这是我尝试过的 Colors m import Colors h implementation Colors UIColor naviga
  • XOR或其他简单的文件混淆方法ios目标c

    我正在开发一个使用受版权保护的 pdf 文件的 ios 应用程序 我正在寻找一些简单的方法来混淆文件以确保安全 这些方法不需要我经历额外的大众市场 CCATS 加密审查流程 但也将确保版权所有者已尽我所能来保证他们的数据安全 当然 我用密码
  • tableView.cellForRowAtIndexPath(indexPath) 返回 nil

    我有一个循环遍历表视图的验证函数 问题是它在某个时刻返回 nil 单元格 for var section 0 section lt self tableView numberOfSections section for var row 0
  • 从应用程序打开/关闭 iPhone 的 Wifi

    我需要打开或关闭 iPhone 中的 wifi 有什么方法可以做到吗 还是被禁止了 私有框架 所有使用公共 SDK 编写的应用程序都经过沙箱处理 他们只能访问苹果认为可以在该沙箱中使用的属性和数据 恐怕 Wi fi 不在列表中 请看一下这个
  • watchOS 2 上的最大内存使用量?

    我没有找到任何有关 watchOS 2 中应用程序可用内存使用的信息 我目前正在为 watchOS 开发一个应用程序 并且在手表端使用 Core Data 当我将 189 个对象中的 166 个加载到数组时 应用程序崩溃 此时的内存使用量为
  • -[_SwiftValueencodeWithCoder:]:无法识别的选择器发送到实例

    尝试使用 NSCoder 时出现错误 玩家 swift class Player NSObject NSCoding private var playerName String private var playerScore Int pri
  • 辅助功能标识符在 iOS 模拟器的辅助功能检查器中不可见

    我想使用辅助功能检查器来验证在模拟器 iOS 9 2 中运行的应用程序中的所有辅助功能标识符 辅助功能检查器能够返回多个辅助功能字段 但不能返回标识符 知道为什么以及如何我能看到它们吗 实际上有一种方法 克里斯 普林斯 Chris Prin
  • 如何动态添加XCTestCase

    我正在为一个白标签项目编写 UI 测试 其中每个应用程序都有一组不同的菜单项 测试点击每个菜单项并截取屏幕截图 使用快车道快照 https docs fastlane tools actions snapshot 目前这一切都发生在一个内部
  • Textview 中心文本对齐 IOS 7

    void observeValueForKeyPath NSString keyPath ofObject id object change NSDictionary change context void context NSLog He
  • iOS 版 Google 地图 sdk 中折线的轮廓

    我的要求是在地图上显示一条绿色折线 但当地图切换到卫星视图时 绿色折线变得不清楚 我无法改变折线的颜色 因此 为了将折线与背景 地图的卫星视图 区分开来 我需要为折线绘制白色轮廓 我浏览了 GMSPolyline 类的文档 但找不到任何可以
  • 为什么我收到 com.facebook.sdk.login 错误 308?

    我正在使用 Xcode 7 0 在 iOS 9 0 2 上进行测试并使用 Facebook SDK 4 7 0 当我登录用户时 大多数时候一切都正常 但有时我不断收到此错误 但我不知道为什么 操作无法完成 com facebook sdk
  • 初始化Object中的空字符串?

    有人使用以下方法来初始化 NSstring NSString astring NSString alloc init 我想知道为什么不直接使用 NSString atring nil or NSString astring 没有semant

随机推荐

  • Java - 包私有类内的方法可访问性?

    如果我有一个包私有的java类 用 类 声明 而不是 公共类 那么里面的方法声明为公共或受保护或包私有实际上没有区别 对吗 那么我应该使用哪个 或者什么时候应该使用哪个 我有点困惑 如果我有一个包私有的java类 用 类 声明 而不是 公共
  • 关闭 Snackbar 时 FloatingActionButton 不会下降

    我正在尝试使用Snackbar 我有一个FloatingActionButton包裹在一个CoordinatorLayout 当 的时候Snackbar显示 按钮已正确向上移动 当它自动关闭时 按钮向下移动 但如果我驳回Snackbar以编
  • 奇怪的空指针异常

    我的 NPE 的 Stacktrace 开头是 Caused by java lang NullPointerException at pl yourvision crm web servlets listExport ProductLis
  • Safari MacOS 异物在 svg 内无法正确缩放

    UPDTATE 由于 Apple 是一家价值 2 万亿美元的公司 让我们尝试通过在此处提交错误报告来让他们解决此问题 https www apple com feedback safari html In Chrome and Firefo
  • IntelliJ:将私钥设置为环境变量不起作用(Spring boot项目)

    我有一个 Spring Boot 项目 如果我使用私钥 多行文本 它工作得很好 这意味着密钥没有问题 但是当我尝试将其设置为 intellij 中的环境变量时 它显示 原因 属性 spring cloud config server git
  • 在另一个应用程序中向我自己的 ContentProvider 请求读取权限

    在一个应用程序中 我在 AndroidManifest 中声明了以下内容提供程序
  • 理解 git Cherry-pick

    来自 svn 背景 我几乎从不分支 因为切换速度 缺乏 以及将分支合并回主干需要一个小时或更长时间 有时 如果我需要修复网站上的问题 我会在主干中进行更改 它将与以前的更改或新功能一起存在 然后转到该文件并执行 svn up path to
  • 在 Perl 正则表达式替换中使用 $1 与 \1 有什么区别?

    我正在调试一些代码 想知道 Perl 正则表达式替换中的 1 和 1 之间是否有任何实际差异 例如 my package name Some Package ButNotThis package name s w w 1 print pac
  • 如何修复错误:此服务需要项目 ID,但无法确定

    我正在尝试从 AppEngine 将数据插入 Google 数据存储区 但收到错误 java lang IllegalArgumentException A project ID is required for this service b
  • numpy fromiter 与列表生成器

    import numpy as np def gen c c np ones 5 dtype int j 0 t 10 while j lt t c 0 j yield c tolist j 1 What I did res np arra
  • 使用选择查询更新表

    所以我在这里读了一些帖子 但我似乎无法在 MySQL 上运行它 几乎我有一个带有 itemid 的记录 计数 我想根据 itemid 更新到我的 items 表中 items popularity 这是我尝试过的 Update items
  • Bash 中命令替换的变量赋值的退出代码

    我对明确执行变量赋值并使用命令替换时命令将返回什么错误代码感到困惑 a false echo 它输出1 这让我认为变量赋值不会清除最后一个错误代码或产生新的错误代码 但是当我尝试这个时 false a echo 它输出0 显然这就是a 返回
  • 有人使用 Swing 的“swingx”扩展吗? [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 我在这里看到了 swingx 的提及和提及 但是 每次
  • 图像缩小算法

    您能帮我找到正确的图像调整大小算法吗 我有一个数字的图像 最大尺寸为 200x200 我需要获得尺寸为 15x15 甚至更小的图像 图像是单色的 黑白 结果应该是相同的 这就是关于我的任务的信息 我已经尝试过一种算法 这里是 xscale
  • 为什么我不能在动态 SQL 的 DDL/SCL 语句中使用绑定变量?

    我正在尝试使用绑定变量在动态 SQL 中执行 SQL 命令 this procedure is a part of PL SQL package Test Pkg PROCEDURE Set Nls Calendar calendar IN
  • 在android模拟器中使用麦克风(Java + Android初学者)

    我在这里读到在 Android 模拟器中使用麦克风可能是可能的 所以我决定尝试一下 尽管答案这个问题说这是不可能的 我复制 粘贴了中提供的代码Android 开发者网站并添加了
  • Django循环导入错误

    我是 Django 新手 我刚刚在 windows vista 上为 python 2 5 安装了 v 1 3 1 使用 setup py install 当我启动 python shell 并尝试导入 django db 时 出现以下循环
  • 使用 H264 编解码器将视频保存在 opencv 中

    我在用opencv python 4 5 1 48 and python3 9码头工人 我想以 h264 格式保存视频 这是我保存视频的功能 import cv2 def save video frames fps 30 video pat
  • Scala中的类型类模式不考虑继承?

    在某些情况下 我正在使用类型类设计 API 但是我遇到了隐式解析的问题 如下所示 如果有一个类型为A的隐式对象但有一个类型为B extends A传递给该方法 则无法找到隐式对象 有没有办法做到这一点 或者调用者是否必须将隐式对象放入每个子
  • MKMapView MKCircle 渲染半径太大的圆

    我面临着 MKCircle 外观的奇怪行为 基本上我试图画一个半径为 8500 公里 任意中心的圆 这是我的代码 private func addCircle mapView removeOverlays mapView overlays