Search code examples
iosswiftcgcontext

CGContext Drawing two adjacent rhomboids produce a very thin gap, how to reduce it?


The two adjacent rectangle is ok as image below.

override func draw(_ rect: CGRect) {
    // Drawing code
    let leftTop = CGPoint(x:50,y:50)
    let rightTop = CGPoint(x:150,y:100)

    let leftMiddle = CGPoint(x:50,y:300)
    let rightMiddle = CGPoint(x:150,y:300)

    let leftDown = CGPoint(x:50,y:600)
    let rightDown = CGPoint(x:150,y:650)

    let context = UIGraphicsGetCurrentContext()
    context?.addLines(between: [leftTop,rightTop,rightMiddle,leftMiddle])
    UIColor.black.setFill()
    context?.fillPath()

    context?.addLines(between: [leftMiddle,rightMiddle,rightDown,leftDown])
    context?.fillPath()


    let leftTop1 = CGPoint(x:200,y:50)
    let rightTop1 = CGPoint(x:300,y:100)

    let leftMiddle1 = CGPoint(x:200,y:300)
    let rightMiddle1 = CGPoint(x:300,y:350)

    let leftDown1 = CGPoint(x:200,y:600)
    let rightDown1 = CGPoint(x:300,y:650)

    context?.addLines(between: [leftTop1,rightTop1,rightMiddle1,leftMiddle1])
    UIColor.black.setFill()
    context?.fillPath()

    context?.addLines(between: [leftMiddle1,rightMiddle1,rightDown1,leftDown1])
    context?.fillPath()
}

You may need to zoom in to see the gap. If I draw a thin line to cover the gap, then any width may overlap if the color has an alpha channel.

enter image description here

Change shapeColor to let shapeColor = UIColor(white: 0.0, alpha: 0.5) and add context?.setShouldAntialias(false) let shapeColor = UIColor(white: 0.0, alpha: 0.5)


Solution

  • This is related to screen resolution. On devices with high resolution one point actually has 2 or 3 pixels. That's why to draw an inclined line iOS draws some edge pixels with some opacity, when 2 lines are next to each other these edge pixels overlap. In your case I was able to fix the issue by making the following change

            let leftTop1 = CGPoint(x:200,y:50)
        let rightTop1 = CGPoint(x:300,y:100)
    
        let leftMiddle1 = CGPoint(x:200,y:300)
        let rightMiddle1 = CGPoint(x:300,y:350)
    
        let leftMiddle2 = CGPoint(x:200,y:300.333)
        let rightMiddle2 = CGPoint(x:300,y:350.333)
    
        let leftDown1 = CGPoint(x:200,y:600)
        let rightDown1 = CGPoint(x:300,y:650)
    
        context?.addLines(between: [leftTop1,rightTop1,rightMiddle1,leftMiddle1])
        UIColor.black.setFill()
    
        context?.fillPath()
    
        context?.addLines(between: [leftMiddle2,rightMiddle2,rightDown1,leftDown1])
        context?.fillPath()
    

    Basically moving down the second rhomboid by 1 pixel (1/3 = 0.333...), I have tested on a screen with 1:3 pixel density, for the solution to work on all devices you'll need to check the scaleFactor of the screen.