I am working on an algorithm for drawing layered rings on a circle that represent different layers of the interior of a planet. My goal is that each layer will be painted pixel by pixel in a randomized distribution according to a proportion of the things that compose that layer, with each component having a different color.
I have managed to get a brute force solution for this, but I'm now trying to optimize it since it is taking a lot of time, here is the code for the first shell:
from PIL import Image, ImageDraw
import numpy as np
width = 1200
height = 800
proportion1 = (0.3,0.6,0.1) # 3 component proportions
colors = ["c1","c2","c3"] # 3 component tags
center_x = width/2
center_y = height/2
radius = 1737 # radius of the planet
core_radius = 300 # radius of the planet's core
core_pixels = round(core_radius*center_x/radius) # pixel radius of the core
first_shell = 600 # outer radius of the first ring
first_shell_pix= round(first_shell*center_x/radius) # pixel radius of first shell
im = Image.new(mode="RGB",size=(width,height),color=(256,256,256)) # Setting up image
# Drawing first shell
for x in range(0,width):
for y in range(0,height):
# Check if pixel falls within the ring coordinates
if (center_x-x)**2 + (center_y-y)**2 >core_pixels**2 and (center_x-x)**2 + (center_y-y)**2 <first_shell_pix**2:
col=np.random.choice(colors,size=1,p=proportion1) # Get random tag
if col =="c1":
color = (0,100,0)
elif col == "c2":
color = (154,205,50)
elif col == "c3":
color = (255,140,0)
im.putpixel((x,y),color) # Paint
The real pictures I want will have several layers and more pixels, and doing the double for loop through all the pixels for each shell would be incredibly inefficient. The only thing that I can think of is having a list with all the pixel coordinates and remove them as they get painted so that the next shell doesn't iterate through all of them, but there has to be a smarter way than that.
Any recommendations?