微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 MKMap 上使用 UIBezierPath addLine 绘制圆弧

如何解决在 MKMap 上使用 UIBezierPath addLine 绘制圆弧

我正在使用 MKOverlayPathRenderer 和 UIBezierPath(画线)来创建圆弧。我不使用 addArc 方法,因为第一个和最后一个半径可能不同。

import Foundation
import UIKit
import MapKit

class IGAArcRenderer: MKOverlayPathRenderer {
    var polyline: MKpolyline
    var arcCentreMapPoint: MKMapPoint
    var initialbearing : Double
    var finalbearing : Double
    
    init(polylineIn: MKpolyline,centreCoordinates: CLLocationCoordinate2D,initbearing: Double,finalbearing: Double) {
        polyline = polylineIn
        self.arcCentreMapPoint = MKMapPoint(centreCoordinates)
        self.initialbearing = initbearing
        self.finalbearing = finalbearing
        super.init(overlay: polyline)
        setup()
    }
    

    override func createPath() {
        let points = polyline.points()
        let startPoint = point(for: points[0])
        let endPoint = point(for: points[1])

        // Defining our new curved path using Bezier path
        let myPath = UIBezierPath()
        myPath.move(to: startPoint)
            
        let arcCentre = point(for: arcCentreMapPoint)

        let startAngle = deg2rad(Deg: CGFloat(self.initialbearing+90))
        let endAngle = deg2rad(Deg: CGFloat(self.finalbearing+90))
            
        // Radius to Start and End Points
        let radiusstart = CGPointdistance(from: arcCentre,to: startPoint)
        let radiusEnd = CGPointdistance(from: arcCentre,to: endPoint)
            
       // Calculate which direction the arc should go when is drawn.
       // If the following value is greater than 0,go clockwise
       //let c = (startPoint.x-arcCentre.x)*(endPoint.y-arcCentre.y)-(startPoint.y-arcCentre.y)*(endPoint.x-arcCentre.x)
       //let direction = c<0 ? false : true


        /* NOTE: This code is working and draws an arc,which is not always perfect due to differences in radius
        myPath.addArc(withCenter: arcCentre,radius: radius,startAngle: startAngle,endAngle: endAngle,clockwise: direction)
        myPath.addLine(to: endPoint)
        */
            
        // Draw an arc by adding a number of lines determined by delta radius and delta angle
        let numpoints = 100
        let stepRadius = (radiusEnd-radiusstart)/CGFloat(numpoints)
        var stepAngle : CGFloat = 0.0
        
        if startAngle>=0 && endAngle>=0 {
            stepAngle = (endAngle-startAngle)/CGFloat(numpoints)
        }
        else if startAngle<0 && endAngle>=0 {
            stepAngle = (endAngle+startAngle)/CGFloat(numpoints)
        }
        else if startAngle>=0 && endAngle<0 {
            stepAngle = (endAngle+startAngle)/CGFloat(numpoints)
        }
        else if startAngle<0 && endAngle<0 {
            stepAngle = (endAngle-startAngle)/CGFloat(numpoints)
        }
        
        print("........ C \(c)")
        print("........ START ANGLE \(startAngle)")
        print("........ END ANGLE \(endAngle)")
        print("........ STEP ANGLE 11 \(endAngle-startAngle)")
        print("........ STEP ANGLE 22 \(stepAngle)")        
        
        // For each point,calculate the CGPoint based on the radius and angle 
        // and draw a line to this point
        for i in 0..<numpoints {
                
            var angleCurrent : CGFloat = 0.0
                
            // Trying to play here to get the right direction
            if startAngle>=0 && startAngle>endAngle {
                angleCurrent = startAngle+CGFloat(i)*stepAngle // ORIGINAL
            }
            else if startAngle<0 && startAngle>endAngle {
                angleCurrent = startAngle-CGFloat(i)*stepAngle // ORIGINAL
            }
            if startAngle>=0 && startAngle<endAngle {
                angleCurrent = startAngle-CGFloat(i)*stepAngle // ORIGINAL
            }
            else {
                angleCurrent = startAngle+CGFloat(i)*stepAngle // ORIGINAL
            }
                
            // Next radius
            let radiusCurrent = radiusstart+CGFloat(i)*stepRadius
                
            // Find the CGPoint
            let pi_x = cos(angleCurrent)*((arcCentre.x-radiusCurrent)-arcCentre.x)-sin(angleCurrent)*((arcCentre.y)-arcCentre.y)+arcCentre.x
            let pi_y = sin(angleCurrent)*((arcCentre.x-radiusCurrent)-arcCentre.x)+cos(angleCurrent)*((arcCentre.y)-arcCentre.y)+arcCentre.y;
            let newLocation = CGPoint(x: pi_x,y: pi_y)

            myPath.addLine(to: newLocation)
        }
            
        myPath.addLine(to: endPoint)

        path = myPath.cgPath 
    }
        
    func CGPointdistanceSquared(from: CGPoint,to: CGPoint) -> CGFloat {
        return (from.x - to.x) * (from.x - to.x) + (from.y - to.y) * (from.y - to.y)
    }

    func CGPointdistance(from: CGPoint,to: CGPoint) -> CGFloat {
        return sqrt(CGPointdistanceSquared(from: from,to: to))
    }
    
    func deg2rad(Deg deg: CGFloat) -> CGFloat {
        return (deg * .pi / 180.0);
    }
    
    func rad2deg(Rad rad: CGFloat) -> CGFloat {
        return (rad * 180 / .pi);
    }
}

有时圆弧画的很完美,有时方向和角度步长的计算有问题。以下是我使用键值得到的一些示例。对于第一个图像,计算第一个弧的适当角度步长(应该在 0.017 左右)时存在问题,但第二个弧绘制得很完美。对于最后一张图片,弧线的方向是错误的,而在所有其他情况下,方向是好的。

如果这里有人对几何有很好的了解,将不胜感激!

enter image description here

enter image description here

enter image description here

enter image description here

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。