为啥我的覆盖线没有根据极坐标公式(swift,ios)产生我在地图中的期望?

Posted

技术标签:

【中文标题】为啥我的覆盖线没有根据极坐标公式(swift,ios)产生我在地图中的期望?【英文标题】:Why is the my overlay line not resulting how I expect in the map based on a polar formulae (swift, ios)?为什么我的覆盖线没有根据极坐标公式(swift,ios)产生我在地图中的期望? 【发布时间】:2016-09-02 13:01:13 【问题描述】:

我的目标

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

我想从我当前的位置沿方位方向、距离的终点画一条线。

只考虑

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

问题

我的线出现了,但总是在同一个方向,在整个世界的距离(而不是 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
    

如果您需要更多信息,请说。感谢您的帮助。

【问题讨论】:

您添加MKPolyline 的代码似乎是正确的。尝试检查您对第二个坐标的计算。 【参考方案1】:

你的数学错了。试试这个:

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 类:

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 类。

【讨论】:

原来有很多问题 - 但这有帮助。非常感谢。

以上是关于为啥我的覆盖线没有根据极坐标公式(swift,ios)产生我在地图中的期望?的主要内容,如果未能解决你的问题,请参考以下文章

为啥这条线没有被覆盖? Xcode 代码覆盖率

为啥我的 iOS 应用没有禁用暗模式?

根据开始和结束地理坐标以指定间隔划分地理线

为啥每次我更改视图并返回它时我的数组都会覆盖自身 - swift 3

Excel折线图或散点折线图线与坐标轴的交点坐标?

使用Xcode / Swift或独角兽精灵灰尘在iPad上覆盖(阻止)或关闭iOS