iOS开发-绘制iOS Developer

【iOS】一种获取圆/弧上等分点的思路

2017-06-01  本文已影响269人  清無

要求:

本文主要讨论的问题有:

1. 给定等分数N,找到圆上相应的等分位置P1...Pn;
问题1

代码实现

    fileprivate func one()
    {
        let N = 10, R: CGFloat = 100
        let angle = 360.0/CGFloat(N) * CGFloat.pi/180.0
        
        for i in 0..<N
        {
            let start = CGFloat(i)*angle - 90*CGFloat.pi/180
            let end = start + angle
            
            // 可以利用贝塞尔path获取圆弧终点的位置CGPoint
            let path = UIBezierPath(arcCenter: view.center, radius: R, startAngle: start, endAngle: end, clockwise: true)
            // 等分点
            let position = path.currentPoint
            // 在相应等分点上绘制元素
            let p = UIBezierPath(arcCenter: position, radius: 10, startAngle: 0, endAngle: 2*CGFloat.pi, clockwise: true)
            let layer = CAShapeLayer()
            layer.fillColor = UIColor.blue.cgColor
            layer.path = p.cgPath
            view.layer.addSublayer(layer)
            
            // 等分弧线段
            let circleLayer = CAShapeLayer()
            circleLayer.lineWidth = 4
            circleLayer.fillColor = nil
            circleLayer.strokeColor = CGFloat(i).remainder(dividingBy: 2) == 0 ? UIColor.red.cgColor : UIColor.green.cgColor
            circleLayer.path = path.cgPath
            view.layer.addSublayer(circleLayer)
        }
    }
实现效果
2. 给定一个弦值W【子元素宽度】和圆的半径R,求最大等分数N;
问题2

代码实现 - 但不知这种算法为何不太准确,有待优化

    fileprivate func two()
    {
        let W: CGFloat = 80, R: CGFloat = 100
        let angle = 2.0 * atan(W / (2.0*R - W))
        let N = Int(2.0 * CGFloat.pi / angle)
        for i in 0..<N
        {
            let start = CGFloat(i)*angle
            let end = start + angle
            
            // 可以利用贝塞尔path获取圆弧终点的位置CGPoint
            let path = UIBezierPath(arcCenter: view.center, radius: R, startAngle: start, endAngle: end, clockwise: true)
            // 等分点
            let position = path.currentPoint
            // 在相应等分点上绘制元素
            let p = UIBezierPath(arcCenter: position, radius: W/2, startAngle: 0, endAngle: 2*CGFloat.pi, clockwise: true)
            let layer = CAShapeLayer()
            layer.fillColor = UIColor.blue.cgColor
            layer.path = p.cgPath
            view.layer.addSublayer(layer)
            
            // 等分弧线段
            let circleLayer = CAShapeLayer()
            circleLayer.lineWidth = 4
            circleLayer.fillColor = nil
            circleLayer.strokeColor = CGFloat(i).remainder(dividingBy: 2) == 0 ? UIColor.red.cgColor : UIColor.green.cgColor
            circleLayer.path = path.cgPath
            view.layer.addSublayer(circleLayer)
        }
    }
实现效果
3. 给定等分数N,求使各个元素不重叠的圆的最大半径R;
问题3

代码实现

fileprivate func three()
    {
        let W: CGFloat = 60, N = 8
        let angle = 2*CGFloat.pi / CGFloat(N)
        var R = W //默认让半径等于W
        
        // 计算 x 是否 <= w/2
        var x = R * sin(angle/2)
        while x < W/2+10 { //10为间距
            R += 1
            x = R * sin(angle/2) //重叠的最小间距
        }
        for i in 0..<N
        {
            let start = CGFloat(i)*angle
            let end = start + angle
            
            // 可以利用贝塞尔path获取圆弧终点的位置CGPoint
            let path = UIBezierPath(arcCenter: view.center, radius: R, startAngle: start, endAngle: end, clockwise: true)
            // 等分点
            let position = path.currentPoint
            // 在相应等分点上绘制元素
            let p = UIBezierPath(arcCenter: position, radius: W/2, startAngle: 0, endAngle: 2*CGFloat.pi, clockwise: true)
            let layer = CAShapeLayer()
            layer.fillColor = UIColor.blue.cgColor
            layer.path = p.cgPath
            view.layer.addSublayer(layer)
            
            // 等分弧线段
            let circleLayer = CAShapeLayer()
            circleLayer.lineWidth = 4
            circleLayer.fillColor = nil
            circleLayer.strokeColor = CGFloat(i).remainder(dividingBy: 2) == 0 ? UIColor.red.cgColor : UIColor.green.cgColor
            circleLayer.path = path.cgPath
            view.layer.addSublayer(circleLayer)
        }
    }
实现效果 元素数越多,半径越大
上一篇下一篇

猜你喜欢

热点阅读