kneesarethebees
kneesarethebees

Reputation: 105

Mondrian Art Program Python

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

Answers (5)

Jacques de Hooge
Jacques de Hooge

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 ()     

enter image description here

Upvotes: 0

cdlane
cdlane

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:

enter image description here

@KaileeCollins, I hope this gives you some ideas for your own project.

Upvotes: 1

Anil_M
Anil_M

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

Terry Jan Reedy
Terry Jan Reedy

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

Wayne Werner
Wayne Werner

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

Related Questions