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

要求:

  • 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)
        }
    }
实现效果
元素数越多,半径越大
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • B树的定义 一棵m阶的B树满足下列条件: 树中每个结点至多有m个孩子。 除根结点和叶子结点外,其它每个结点至少有m...
    文档随手记阅读 14,592评论 0 25
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 32,720评论 18 399
  • 一、python 变量和数据类型 1.整数 Python可以处理任意大小的整数,当然包括负整数,在Python程序...
    绩重KF阅读 5,869评论 0 1
  • 一下午基本就是在聊天,傍晚回家时坐在地铁上居然忍不住地打瞌睡,看来说话挺耗神的,但迷糊中脑子还是没有停,一直有些念...
    兮兮0225阅读 1,495评论 0 0

友情链接更多精彩内容