为什么我的叠加线没有产生我在基于极坐标公式 (swift、ios) 的地图中所期望的结果?

Why is the my overlay line not resulting how I expect in the map based on a polar formulae (swift, ios)?

我的目标

根据三位数据绘制一条线:给定坐标、距离、方位角。

我想从我的当前位置沿方位角方向在距离的终点绘制一条线。

切记

我确实在地图上找到了一条线,每次当前位置都会更新,所以在这个意义上没有问题(我显示的代码可能不包括所有定义 - 但假设没有编译错误等)

问题

我的线出现了,但总是在同一个方向,在整个世界的距离(而不是 1 公里!)。我尝试更改标题输入但仍然得到相同的行。

代码

func drawHeadingLine(currentLocation: [Double], heading: Double){

        //to radians
        let headingR = heading * 0.0174533;

        if viewLine != nil{
            mapView.removeOverlay(viewLine);
        }
        // setup data for polar formulae
        let pi = M_PI;
        let currentLONG = currentLocation[0];
        let currentLAT = currentLocation[1];
        let currentLongRadian = currentLocation[0] * (pi * 180);
        let currentLatRadian = currentLocation[1] * (pi * 180);
        let lineDistance: Double = 1; //km
        let earthRadius: Double = 6378.1; //km
        let angularDistance: Double = lineDistance / earthRadius;

        //use polar formulae (given point, distance, bearing) for line end point

        let latitude2 = asin( sin(currentLatRadian) * cos(angularDistance)
                                + cos(currentLatRadian) * sin(angularDistance) * cos(headingR) );

        let longitude2 = currentLongRadian + atan2( cos(angularDistance) - sin(currentLatRadian) * sin(latitude2),
                                              sin(headingR) * sin(angularDistance) * cos(currentLatRadian));


        var coordinates1 = CLLocationCoordinate2D();
        coordinates1.longitude = currentLONG;
        coordinates1.latitude = currentLAT;

        var coordinates2 = CLLocationCoordinate2D();
        coordinates2.longitude = longitude2;
        coordinates2.latitude = latitude2;

        var lineCoords = [ coordinates1,coordinates2];

        viewLine = MKPolyline(coordinates: &lineCoords, count: lineCoords.count);
        self.mapView.addOverlay(viewLine);

    }


func mapView(mapView: MKMapView!, viewForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {

        if (overlay is MKPolyline) {
            viewLine = overlay;
            let line = MKPolylineRenderer(overlay: viewLine);
            line.strokeColor = UIColor.redColor().colorWithAlphaComponent(0.5);
            line.lineWidth = 5;
            return line;
        }

        return nil
    }

请说明您是否需要更多信息。感谢您的帮助。

你的数学有问题。试试这个:

func drawHeadingLine(currentLocation: [Double], heading: Double){
    if viewLine != nil {
        mapView.removeOverlay(viewLine!)
    }

    let (lat, long) = (currentLocation[0], currentLocation[1])
    let headingR = heading * M_PI / 180.0
    let lineDistance = 1.0 //km

    let latDelta = cos(headingR) * lineDistance / EarthMeasurement.lengthOfLatitude(at: lat)
    let longDelta = sin(headingR) * lineDistance / EarthMeasurement.lengthOfLongitude(at: lat)

    let pointA = CLLocationCoordinate2D(latitude: lat, longitude: long)
    let pointB = CLLocationCoordinate2D(latitude: lat + latDelta, longitude: long + longDelta)

    // For debugging, let's calculate a geodesic distance between these 2 points
    // Results are in meters
    let locationA = CLLocation(latitude: lat, longitude: long)
    let locationB = CLLocation(latitude: lat + latDelta, longitude: long + longDelta)
    print("heading = \(heading), distance = \(locationA.distanceFromLocation(locationB)")

    var coordinates = [pointA, pointB]
    let polyline = MKPolyline(coordinates: &coordinates, count: 2)
    self.mapView.addOverlay(polyline)
}

EarthMeasurement class:

final class EarthMeasurement {
    static func lengthOfLatitude(at latitude: Double) -> Double {
        return 110.574
    }

    static func lengthOfLongitude(at latitude: Double) -> Double {
        let latitudeR = latitude * M_PI / 180.0
        return cos(latitudeR) * 111.320
    }
}

思路是Map Kit处理的是纬度和经度,而不是公里,所以我们需要知道纬度/经度有多少公里。这远非简单,因为地球不是一个完美的球体。但我们可以做出近似值:

  • 当您靠近两极时,1 度纬度的长度确实会变长,但差异很小:赤道和两极之间大约相差 1 公里(或 1%)。我们可以忽略它并使用赤道的长度,根据 Wikipedia 是 111.574km。
  • 1纬度的长度公式取自this question.

由于我们使用的是近似值,因此这不会给出恰好 1 公里远的点。误差在赤道附近的纬度较小,并且随着您接近两极(~10m)而逐渐增加。如果您想要更准确的结果,请相应地调整 EarthMeasurement class。