【问题标题】:How to draw circle overlay on MapKit that surrounds several annotations/coordinates?如何在围绕多个注释/坐标的 MapKit 上绘制圆形叠加层?
【发布时间】:2018-02-28 16:53:24
【问题描述】:

我有一个数组[CLLocationCoordinate2D],我想在MKMapView 上围绕所有这些坐标画一个圆圈。

我已经设法围绕单个CLLocationCoordinate2D 画了一个圆圈:

let coordinate = CLLocationCoordinate2D(latitude: 53, longitude: 27)
self.mapView.add(MKCircle(center: coordinate, radius: 100))

extension MapViewController: MKMapViewDelegate {
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        guard overlay is MKCircle else { return MKOverlayRenderer() }

        let circle = MKCircleRenderer(overlay: overlay)
        circle.strokeColor = UIColor.red
        circle.fillColor = UIColor(red: 255, green: 0, blue: 0, alpha: 0.1)
        circle.lineWidth = 1
        return circle
    }
}

如何绘制一个环绕/包含所有坐标的圆?,如下所示:

【问题讨论】:

  • 您需要找到两个具有最大距离的注释,并将此距离假定为圆的直径并更新圆以获得新的直径。
  • 感谢您的回复,竭尽全力让这个工作正常进行,但远未成功
  • 如果您有任何问题,请告诉我
  • 很高兴您愿意提供帮助,谢谢

标签: ios swift geometry mapkit mapkitannotation


【解决方案1】:

我想出了MKCoordinateRegion初始化器,它提供了区域的坐标,扩展有一个计算属性来提供区域的半径。

extension MKCoordinateRegion {

    init?(from coordinates: [CLLocationCoordinate2D]) {
        guard coordinates.count > 1 else { return nil }

        let a = MKCoordinateRegion.region(coordinates, fix: { $0 }, fix2: { $0 })
        let b = MKCoordinateRegion.region(coordinates, fix: MKCoordinateRegion.fixMeridianNegativeLongitude, fix2: MKCoordinateRegion.fixMeridian180thLongitude)

        guard (a != nil || b != nil) else { return nil }
        guard (a != nil && b != nil) else {
            self = a ?? b!
            return
        }

        self = [a!, b!].min(by: { $0.span.longitudeDelta < $1.span.longitudeDelta }) ?? a!
    }

    var radius: CLLocationDistance {
        let furthest = CLLocation(latitude: self.center.latitude + (span.latitudeDelta / 2),
                                  longitude: center.longitude + (span.longitudeDelta / 2))
        return CLLocation(latitude: center.latitude, longitude: center.longitude).distance(from: furthest)
    }

    // MARK: - Private
    private static func region(_ coordinates: [CLLocationCoordinate2D],
                               fix: (CLLocationCoordinate2D) -> CLLocationCoordinate2D,
                               fix2: (CLLocationCoordinate2D) -> CLLocationCoordinate2D) -> MKCoordinateRegion? {
        let t = coordinates.map(fix)
        let min = CLLocationCoordinate2D(latitude: t.min { $0.latitude < $1.latitude }!.latitude,
                                         longitude: t.min { $0.longitude < $1.longitude }!.longitude)
        let max = CLLocationCoordinate2D(latitude: t.max { $0.latitude < $1.latitude }!.latitude,
                                         longitude: t.max { $0.longitude < $1.longitude }!.longitude)

        // find span
        let span = MKCoordinateSpanMake(max.latitude - min.latitude, max.longitude - min.longitude)

        // find center
        let center = CLLocationCoordinate2D(latitude: max.latitude - span.latitudeDelta / 2,
                                            longitude: max.longitude - span.longitudeDelta / 2)

        return MKCoordinateRegion(center: fix2(center), span: span)
    }

    private static func fixMeridianNegativeLongitude(coordinate: CLLocationCoordinate2D) -> CLLocationCoordinate2D {
        guard (coordinate.longitude < 0) else { return coordinate }

        let fixedLng = 360 + coordinate.longitude
        return CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: fixedLng)
    }

    private static func fixMeridian180thLongitude(coordinate: CLLocationCoordinate2D) -> CLLocationCoordinate2D {
        guard (coordinate.longitude > 180) else { return coordinate }

        let fixedLng = -360 + coordinate.longitude
        return CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: fixedLng)
    }

}

用法:

let coordinates: [CLLocationCoordinate2D] = self.mapView.annotations.map{ $0.coordinate }
if let region = MKCoordinateRegion(from: coordinates) {
    self.mapView.add(MKCircle(center: region.center, radius: region.radius))
}

结果正是我想要的,能够处理穿越180经线的坐标:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多