Reputation: 105
I'm trying to create a Mondrian Art program....I have the code that generates the squares randomly..but I'm having trouble randomly filling the squares with primary colors? Does anyone know how to fix that? This is my code:
import turtle
import random
turtle.screensize(1000,1000)
turtle.setworldcoordinates(-500,-500,500,500)
piet = turtle.Turtle()
piet.speed(300)
#primary colors, red, blue, yellow
#piet.color(red,blue,yellow)
rectangles = int(input('How many rectangles should be drawn? '))
rectangle_w = int(input('What should be the max width of the rectangles? '))
rectangle_h = int(input('What should be the max height of the rectangles? '))
def mondrian(t,random_w,random_h):
piet.begin_fill()
for number_r in range(1):
for box in range(2):
t.left(90)
t.forward(random_w)
t.left(90)
t.forward(random_h)
piet.end_fill()
mondrian(piet,random.randint(10,rectangle_w),random.randint(10,rectangle_h))
def repeat_mondrian():
for i in range(rectangles - 1):
mondrian(piet, random.randint(10, rectangle_w), random.randint(10, rectangle_h))
repeat_mondrian()
Thanks! :)
Upvotes: 4
Views: 6378
Reputation: 7000
Yet another implementation. This program can be run in a browser, select the 'Mondrian' demo at: http://www.transcrypt.org/live/turtle_site/turtle_site.html and wait a while, the paining changes every few seconds.
You can modify the program and see what the effect is. It also runs using Python 3.5 from the console.
# Inspired by our cat Pietje
from turtle import *
from random import *
speed (0)
colors = ('gray', 'green', 'red', 'white', 'blue', 'yellow')
delta = 8
threshold = 100
color ('black', 'black')
def maybe (bias = None):
return choice ([False, True, bias, bias] if bias != None else [False, True])
def between (a, b):
return a + (0.2 + 0.3 * random ()) * (b - a)
recentColors = ['black', 'black']
def originalColor ():
global recentColors
while True:
result = choice (colors)
if not result in recentColors:
recentColors = [result, recentColors [0]]
return result
def rect (xMin, yMin, xMax, yMax):
for aColor in ('black', originalColor ()):
color (aColor, aColor)
up ()
goto (xMin, yMin)
down ()
begin_fill ()
goto (xMax, yMin)
goto (xMax, yMax)
goto (xMin, yMax)
goto (xMin, yMin)
end_fill ()
xMin += delta
yMin += delta
xMax -= delta
yMax -= delta
def draw (xMin = -250, yMin = -300, xMax = 250, yMax = 300):
if xMax - xMin > threshold and yMax - yMin > threshold:
if maybe (xMax - xMin > yMax - yMin):
xMid = between (xMin, xMax)
if maybe ():
draw (xMin, yMin, xMid, yMax)
rect (xMid, yMin, xMax, yMax)
else:
rect (xMin, yMin, xMid, yMax)
draw (xMid, yMin, xMax, yMax)
else:
yMid = between (yMin, yMax)
if maybe ():
draw (xMin, yMin, xMax, yMid)
rect (xMin, yMid, xMax, yMax)
else:
rect (xMin, yMin, xMax, yMid)
draw (xMin, yMid, xMax, yMax)
else:
rect (xMin, yMin, xMax, yMax)
ontimer (lambda: (clear (), draw ()), 2000)
draw ()
done ()
Upvotes: 0
Reputation: 41872
As a fan, I see a Mondrian as being more about dividing space with hints of tension and recursion rather than random squares. With more white space than color.
If these folks can teach a computer to paint a Rembrandt, then we should be able to collectively teach one to paint a Mondrian. Here's my humble offering towards this effort:
import turtle as turtle_graphics
import random
import collections
BORDER_COLOR = '#000000' # so you can add 'black' to COLORS below
BORDER_WIDTH = 10
MINIMUM_DIVISIBLE_PORTION = .2 # limits recursion
COLORS = ('white', 'white', 'red', 'white', 'blue', 'yellow') # multiple 'white' to increase probability
Bounds = collections.namedtuple('Bounds', ['x', 'y', 'width', 'height'])
PICTURE_BOUNDS = Bounds(x=-250, y=-300, width=500, height=600)
def fill_rectangle(turtle, bounds, color=BORDER_COLOR):
""" Fill a rectangle with the border color (by default) and then fill the center with a bright color """
turtle.penup()
turtle.goto(bounds.x, bounds.y)
turtle.color(color)
turtle.pendown()
turtle.begin_fill()
for _ in range(2):
turtle.forward(bounds.width)
turtle.left(90)
turtle.forward(bounds.height)
turtle.left(90)
turtle.end_fill()
turtle.penup()
if color == BORDER_COLOR:
fill_rectangle(turtle, Bounds(bounds.x + BORDER_WIDTH, bounds.y + BORDER_WIDTH, bounds.width - BORDER_WIDTH*2, bounds.height - BORDER_WIDTH*2), random.choice(COLORS))
def mondrian(piet, bounds):
""" Divide, fill and divide & fill some more. Intuitively and recursively """
if bounds.width < bounds.height:
dimension = 'height'
random_dimension = random.randint(getattr(bounds, dimension) // 5, 2 * getattr(bounds, dimension) // 3)
bounds_yin = Bounds(bounds.x, y=bounds.y + random_dimension, width=bounds.width, height=bounds.height - random_dimension)
bounds_yang = Bounds(bounds.x, bounds.y, bounds.width, random_dimension)
else:
dimension = 'width'
random_dimension = random.randint(getattr(bounds, dimension) // 5, 2 * getattr(bounds, dimension) // 3)
bounds_yin = Bounds(bounds.x, bounds.y, random_dimension, bounds.height)
bounds_yang = Bounds(x=bounds.x + random_dimension, y=bounds.y, width=bounds.width - random_dimension, height=bounds.height)
if getattr(bounds_yin, dimension) > getattr(bounds_yang, dimension):
bounds_paint, bounds_divide = bounds_yang, bounds_yin
else:
bounds_paint, bounds_divide = bounds_yin, bounds_yang
fill_rectangle(piet, bounds_paint)
if getattr(bounds_divide, dimension) < MINIMUM_DIVISIBLE_PORTION * getattr(PICTURE_BOUNDS, dimension):
fill_rectangle(piet, bounds_divide)
else:
mondrian(piet, bounds_divide)
def paint_canvas(dummy_x=0, dummy_y=0):
""" Runs the program and can be used as an event handler """
turtle_graphics.onscreenclick(None)
fill_rectangle(turtle_graphics, PICTURE_BOUNDS, 'black')
mondrian(turtle_graphics, PICTURE_BOUNDS)
turtle_graphics.onscreenclick(paint_canvas)
turtle_graphics.screensize(PICTURE_BOUNDS.width, PICTURE_BOUNDS.height)
turtle_graphics.speed('fastest')
turtle_graphics.hideturtle()
paint_canvas()
turtle_graphics.listen()
turtle_graphics.mainloop()
If you don't like the painting you get, click on the canvas and it will paint another, hopefully more to your liking:
@KaileeCollins, I hope this gives you some ideas for your own project.
Upvotes: 1
Reputation: 11453
I don't use much turtle , but upon investigation looks like you may have missed to put pen down before begin_fill
and set piet.color
after that.
** Update **
Looks like fillcolor
is way to go as you dont need to do pendown or penup.
Here is updated code for mondarian
function.
def mondrian(t,random_w,random_h):
piet.begin_fill()
for number_r in range(1):
for box in range(2):
piet.fillcolor(random.choice(('red','blue','yellow')))
t.left(90)
t.forward(random_w)
t.left(90)
t.forward(random_h)
piet.end_fill()
Upvotes: 0
Reputation: 19154
Here is your program slightly cleaned up, and with inputs temporarily fixed for ease of development. Notice that lower right corner of all rectangles is the origin. You should randomize that also.
import turtle
import random
turtle.screensize(1000,1000)
turtle.setworldcoordinates(-500,-500,500,500)
piet = turtle.Turtle()
piet.speed(300)
rectangles = 8 #int(input('How many rectangles '))
rectangle_w = 500 #int(input('Max width of the rectangles? '))
rectangle_h = 500 #int(input('Max height of the rectangles? '))
def mondrian(t,random_w, random_h):
piet.fillcolor(random.choice(('red','blue','yellow')))
piet.begin_fill()
for box in range(2):
t.left(90)
t.forward(random_w)
t.left(90)
t.forward(random_h)
piet.end_fill()
def repeat_mondrian():
for i in range(rectangles):
mondrian(piet,
random.randint(10, rectangle_w),
random.randint(10, rectangle_h))
repeat_mondrian()
Upvotes: 2
Reputation: 51837
You simply need to change the turtle.color
(which you have commented out, just in the wrong place:
def mondrian(t, random_w, random_h):
piet.begin_fill()
piet.color(random.choice(['red', 'blue', 'yellow']))
# rest of your code goes here
Upvotes: 0