iosswiftpencilkit

How do I create a PKDrawing programmatically, from CGPoints?


I've watched this WWDC session as well as its sample project: https://developer.apple.com/documentation/pencilkit/inspecting_modifying_and_constructing_pencilkit_drawings

However, when I try to plot CGPoints on my drawing canvas, nothing shows up.

Here's my setup:

var points: [CGPoint] = []
(500...1000).forEach { x in
    (500...1000).forEach { y in
        points.append(CGPoint(x: x, y: y))
    }
}
let strokePoints = points.map {
    PKStrokePoint(location: $0, timeOffset: 0, size: CGSize(uniform: 1), opacity: 2, force: 1, azimuth: 1, altitude: 1)
}
let strokePath = PKStrokePath(controlPoints: strokePoints, creationDate: Date())
let stroke = PKStroke(ink: PKInk(.pen, color: .systemGreen), path: strokePath)
canvasView.drawing = PKDrawing(strokes: [ stroke ])

Solution

  • I figured that the problem was on the size of my stroke. This will work:

    PKStrokePoint(location: point, timeOffset: 0, size: CGSize(uniform: 3), opacity: 1, force: 0, azimuth: 0, altitude: 0)
    

    Note that it must be at least 3. If it's 1, it's invisible, if it's 2 it's semi-transparent. This doesn't seem to be related to the screen's scale (my iPad Pro's UIScreen.main.scale = 2.0) so I just hardcoded it at 3, to represent a single pixel.


    To achieve this result, I drew a single pixel on the screen using the pencil and logged its content, which showed me these parameters:

    ▿ PencilKit.PKStrokePoint
      - strokePoint: <PKStrokePoint: 0x600001ad8f60 location={445, 333.5} timeOffset=0.000000 size={3.084399938583374, 3.084399938583374} opacity=0.999985 azimuth=-3.141593 force=0.000000 altitude=1.570796> #0
        - super: NSObject
    

    So then I played around with those values (for size, opacity, azimuth, force and altitude), and figured that none of those except the size and opacity matter. That's why I set them as all as zero values in my code.