美文网首页iOS开发-绘制iOS Developer
【iOS】一种获取圆/弧上等分点的思路

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

作者: 清無 | 来源:发表于2017-06-01 17:01 被阅读269次

    要求:

    • Platform: iOS8.0+
    • Language: Swift3.1
    • Editor: Xcode8.3.2

    本文主要讨论的问题有:

    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)
            }
        }
    
    实现效果 元素数越多,半径越大

    相关文章

      网友评论

        本文标题:【iOS】一种获取圆/弧上等分点的思路

        本文链接:https://www.haomeiwen.com/subject/mqkefxtx.html