在 Swift 中使用 Core Graphics 填充多边形

Fill a polygon using Core Graphics in Swift

目标是在 Swift 中使用 Core Graphics 填充多边形。

如果所有端点都是已知的,则以下代码将执行此操作。

   func drawPolySegment() {
        let renderer = UIGraphicsImageRenderer(size: CGSize(width: 512, height: 512))

        let img = renderer.image { ctx in

            let endpoints = [
                CGPoint(x: 200, y: 175),
                CGPoint(x: 270, y: 170),
                CGPoint(x: 300, y: 100)
            ]

            ctx.cgContext.addLines(between: endpoints)

            UIColor.yellow.setFill()
            ctx.cgContext.drawPath(using: .fillStroke)
        }
        imageView.image = img
    }

但是,所需形状的端点不容易获得,因此选择了一种更通用的方法,即使用 rotate(by:)、move(to:)、addline(to:)、translate(by:)方法如下:

    func drawPolygon() {
        let renderer = UIGraphicsImageRenderer(size: CGSize(width: 512, height: 512))

        let img = renderer.image { ctx in
            let apexes: CGFloat = 3   //5     //6
            let length: CGFloat = 500 //190   //140
            let angle: CGFloat = 2 * π / apexes
            let zero: CGFloat = 0

            UIColor.brown.setStroke()
            UIColor.yellow.setFill()
            ctx.cgContext.setLineWidth(10)
            ctx.cgContext.setLineCap(.round)

            ctx.cgContext.translateBy(x: 256, y: 5)

            for segment in 0..<Int(apexes * 2) {
                if segment == 0 {
                    ctx.cgContext.rotate(by: angle)
                } else if segment % 2 == 0 {
                    ctx.cgContext.rotate(by: 2 * angle)
                } else {
                    ctx.cgContext.rotate(by: -angle)
                }
                ctx.cgContext.move(to: CGPoint(x: zero, y: zero))
                ctx.cgContext.addLine(to: CGPoint(x: length, y: zero))
                ctx.cgContext.translateBy(x: length, y: zero)
            }

            ctx.cgContext.drawPath(using: .fillStroke)
        }

        imageView.image = img
    }

上面的代码生成了一个漂亮的轮廓形状,但不会填充颜色。 "apexes" 和 "length" 注释掉的值对创建的 512 x 512 渲染有效 space。为什么形状填充第一个代码示例而不是第二个?第二个代码示例缺少什么来填充形状?

您不是在绘制多边形,而是在绘制 3 条独立的未连接线。每个 move(to:) 开始一个新的多边形。

您可以通过仅对第一段执行 move(to:) 来解决此问题:

for segment in 0..<Int(apexes * 2) {
    if segment == 0 {
        ctx.cgContext.rotate(by: angle)
        ctx.cgContext.move(to: CGPoint(x: zero, y: zero))
    } else if segment % 2 == 0 {
        ctx.cgContext.rotate(by: 2 * angle)
    } else {
        ctx.cgContext.rotate(by: -angle)
    }

    ctx.cgContext.addLine(to: CGPoint(x: length, y: zero))
    ctx.cgContext.translateBy(x: length, y: zero)
}

结果:

apexes: 3, length: 500

apexes: 5, length: 190

apexes: 6, length: 140