将标记放置在 MKPolyLine 的中心

问题描述 投票:0回答:1

我正在使用 MapKit 在地图上的两点之间绘制一条直线,并尝试在中心放置一个标记。当距离很小时,一切都很好,但是当距离更大时,中间的标记会偏离线。是否可以使其更准确?由于 PolyLine,我使用 MKMapView 的 UIViewRepresentable ,但我想在这种情况下这应该不重要。我正在复制 MapView 以防有人想要重现,但在我看来应该没问题。我居中只是一个例子,理想情况下,我想在线的任何部分放置一个标记。

struct ContentView: View {
    let tfs = CLLocationCoordinate2D(latitude: 28.047477135170762, longitude: -16.572272806214418)
    let london = CLLocationCoordinate2D(latitude: 51.507277135170762, longitude: 0.127672806214418)
    private var lineCoordinates: [CLLocationCoordinate2D]
    let middle: CLLocationCoordinate2D
    init() {
        self.lineCoordinates = [tfs, london]
        middle = CLLocationCoordinate2D(latitude: (london.latitude + tfs.latitude) / 2, longitude: (london.longitude + tfs.longitude) / 2)
    }
  var body: some View {
    MapView(
      currentPosition: middle,
      lineCoordinates: lineCoordinates
    )
      .edgesIgnoringSafeArea(.all)
  }
}

struct MapView: UIViewRepresentable {
  let currentPosition: CLLocationCoordinate2D
  let lineCoordinates: [CLLocationCoordinate2D]

  func makeUIView(context: Context) -> MKMapView {
    let mapView = MKMapView()
    mapView.delegate = context.coordinator
    mapView.region = MKCoordinateRegion(coordinates: lineCoordinates)

    let polyline = MKPolyline(coordinates: lineCoordinates, count: lineCoordinates.count)
    mapView.addOverlay(polyline)

      let annotation = MKPointAnnotation()
      annotation.coordinate = currentPosition
      annotation.title = "Current position"
      mapView.addAnnotation(annotation)

    return mapView
  }

  func updateUIView(_ view: MKMapView, context: Context) {}

  func makeCoordinator() -> Coordinator {
    Coordinator(self)
  }

}

class Coordinator: NSObject, MKMapViewDelegate {
  var parent: MapView

  init(_ parent: MapView) {
    self.parent = parent
  }

  func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
    if let routePolyline = overlay as? MKPolyline {
      let renderer = MKPolylineRenderer(polyline: routePolyline)
      renderer.strokeColor = UIColor.systemBlue
      renderer.lineWidth = 10
      return renderer
    }
    return MKOverlayRenderer()
  }
}

extension MKCoordinateRegion {
    init(coordinates: [CLLocationCoordinate2D], spanMultiplier: CLLocationDistance = 1.3) {
        var topLeftCoord = CLLocationCoordinate2D(latitude: -90, longitude: 180)
        var bottomRightCoord = CLLocationCoordinate2D(latitude: 90, longitude: -180)

        for coordinate in coordinates {
            topLeftCoord.longitude = min(topLeftCoord.longitude, coordinate.longitude)
            topLeftCoord.latitude = max(topLeftCoord.latitude, coordinate.latitude)

            bottomRightCoord.longitude = max(bottomRightCoord.longitude, coordinate.longitude)
            bottomRightCoord.latitude = min(bottomRightCoord.latitude, coordinate.latitude)
        }

        let cent = CLLocationCoordinate2D.init(latitude: topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5, longitude: topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5)
        let span = MKCoordinateSpan.init(latitudeDelta: abs(topLeftCoord.latitude - bottomRightCoord.latitude) * spanMultiplier, longitudeDelta: abs(bottomRightCoord.longitude - topLeftCoord.longitude) * spanMultiplier)

        self.init(center: cent, span: span)
    }
}

mapkit mkmapview mkannotation mkpolyline
1个回答
0
投票

我想通了,其实我确实需要使用

MKGeodesicPolyline
,所以这条线会遵循地球的曲率来显示最短路径,但我计算线中间的方式也不正确

CLLocationCoordinate2D(latitude: (london.latitude + tfs.latitude) / 2, longitude: (london.longitude + tfs.longitude) / 2)

这仅适用于 2D 坐标空间,在计算地图上的距离或路径时不能在现实生活场景中使用。有一些高级公式可以做到这一点,但我最终只是通过这个gist获得了坐标内的点。我正在获取线条的坐标,并在想要放置标记时从这些点中进行选择。

© www.soinside.com 2019 - 2024. All rights reserved.