Gradient rings from Python for Designers tutorial



  • Hello everyone!!!

    I'm attempting to solve the ex­er­cise 14.4 of @roberto-arista 's pythonfordesigners.com/chapters/workbook/ I'm having a problem with my approach, I decided to use circles instead of lines and I couldn't find a way to make a smooth gradient without having a weird hole 🕳 in the middle of the right top and right bottom blending, here's a photo of it:

    Screen Shot 2021-01-11 at 13.55.29.png

    # 14.4
    def donuts(circSize=10, cnvSize=200):
        
        def intrp(factor, val1, val2):
            return val1 + (val2 - val1) * factor
            
        def intrRgb(factor, col1, col2):
            r = intrp(factor, col1[0], col2[0])
            g = intrp(factor, col1[1], col2[1])
            b = intrp(factor, col1[2], col2[2])
            return r, g, b
            
        def circCoords(radius, circSize=10):
            cirCoords = []
            an = 0
            anMulti = 0
            for i in range(cnvSize+1):
                for j in range(cnvSize):
                    cirCoords.append([
                        radius * sin(pi * 2 * an / 360) - halfCirc,
                        radius * cos(pi * 2 * an / 360) - halfCirc
                    ])
                    an += 360/(cnvSize*cnvSize)
            return sorted(cirCoords)
            
        def mapColors(c1, c2, c3, c4):
            colors = []
            for x in range(cnvSize):
                xFactor = x/cnvSize
                for y in range(cnvSize):
                    yFactor = y / cnvSize
                    lftClr = intrRgb(yFactor, c4, c1)
                    rgtClr = intrRgb(yFactor, c3, c2)
                    colors.append(intrRgb(xFactor, lftClr, rgtClr))       
            return colors
        
        halfCirc = circSize/2
        colors = {'lftTop': (1, 0, 0.8), 'rgtTop': (1, 1, 0.3), 'rgtBtm': (1, .8, 0), 'lftBtm': (0, 0.5, 1)} 
        
        colors = mapColors(colors['lftTop'], colors['rgtTop'], colors['rgtBtm'], colors['lftBtm'])
        circles = [circCoords(cnvSize*0.4, circSize), circCoords(cnvSize*0.25, circSize), circCoords(cnvSize*0.1, circSize)]
        
        newPage(cnvSize, cnvSize)
        inc = 0
        for x in range(cnvSize):
            for y in range(cnvSize):
                fill(*colors[inc])
                if x == 0 and y == 0 or x == 0 and y == cnvSize-1 or x == cnvSize-1 and y == 0 or x == cnvSize-1 and y == cnvSize-1:
                    oval(x - halfCirc, y - halfCirc, circSize, circSize)
                if y == int(circles[0][inc][1]) + cnvSize/2 - 1 or y == int(circles[0][inc][1]) + cnvSize - 100:
                    for circ in circles:
                        with savedState():
                            translate(cnvSize/2, cnvSize/2)
                            oval(circ[inc][0], circ[inc][1], circSize, circSize)
                inc += 1
    
    # Call the function
    donuts()
    

    Hope you can help me, feedback on my approach would be great too, thank you!!!!!!!


  • admin

    I think the circCoords is a bit overkill 🙂
    its creating an circular x, y coordinate while looping over the width and height of the page. You are drawing a lot of ovals 🙂

    radius = 100
    translate(width() *.5, height() *.5)
    
    inSteps = 1
    # inSteps = 15
    
    for angle in range(0, 360, inSteps):
        factor = angle / 360 * 2
        if factor > 1:
            factor = 2 - factor    
        
        x = cos(radians(angle)) * radius
        y = sin(radians(angle)) * radius
        
        fill(factor, 0, 1)
        oval(x - 5, y - 5, 10, 10)