Forum Archive

draw_heart() now looks really cool

ccc
# -*- coding: utf-8 -*-
# draw_heart.py
# http://gaming.jhu.edu/~phf/2012/fall/cs112/assignment-02.pdf or
# https://plus.google.com/app/basic/stream/z12lunmjbx33vh5bt04cilrpelnzcbhoorg0k

#Draw a heart
import canvas, sys
from math import sin, cos, pi

w = h = 600

def draw_heart():
    #canvas.move_to(w/2, h/2)
    canvas.move_to(0, 0)
    for t_int in xrange(int(2 * pi * 1000)):
        t = t_int / 1000
        x = 16*(sin(t) ** 3)
        y = 13*cos(t) - 5*cos(2*t) - 2*cos(3*t) - cos(4*t)
        canvas.add_line(x * 150, y * 150)
    canvas.close_path()
    canvas.set_line_width(3)
    canvas.draw_path()

print('Starting...')
canvas.set_size(w, h)
draw_heart()
bee18

Try this one...

# draw a heart using equation
import canvas, sys, random
from console import clear
from datetime import datetime
from math import sin, cos, pi

w = h = 600 # canvas size
detail = random.random() * 100 # larger is slower 
# almost perfect : 12.485 75.05 125.3
# half left : 12.525
# half right : 12.605
scale = 15 # larger is bigger
origin = w/2 # plot origin on canvas

def draw_heart(outline = False):
    first = True 
    for t in xrange(int(2*pi * detail)):
        t = t * detail
        # heart equation
        x = 16*(sin(t) ** 3)
        y = 13*cos(t) - 5*cos(2*t) - 2*cos(3*t) - cos(4*t)
        # scale result
        x = origin + x * scale
        y = origin + y * scale + scale*2
        # hide first line
        if first:
            canvas.move_to(x, y)
            first = False 
        else: 
            canvas.add_line(x, y)
    # set color
    canvas.set_fill_color(1,0.5,0.5)
    canvas.set_stroke_color(0.5,0,0)
    canvas.set_line_width(detail/2)
    # draw heart
    if outline: 
        canvas.draw_path()
    else:
        canvas.close_path()
        canvas.fill_path()

clear()
print 'Calculating... d =',detail
start = datetime.now()
canvas.set_size(w,h)
canvas.draw_rect(0,0, w,h)
#canvas.draw_line(0,h/2,w,h/2)
#canvas.draw_line(w/2,0,w/2,h)
draw_heart(True) # outlined
draw_heart() # filled
stop = datetime.now()
print(stop-start)

Updated with comment and constant separation. Another update, add drawing timer. Another update, add fill mode via function argument. Another update, pick detail value randomly, creating beautiful images out of the equation.

bee18

Output sample: https://pic.twitter.com/cGE1W9e3j6

Output sample:

ccc

Awesome bee... Just one more nagging question: https://github.com/cclauss/Pythonista_canvas

bee18

I couldn't find a floodfill function to fill an arbitrary area with a specified color. If you want to get a smooth edge of the heart, try to play with the detail constant. I found 62.66 seems to be smooth enough. I also found 12.66, 25, 37.66, etc seem to be smooth as well. Try to find other values.

update: Well, fill_path() does fill the inner part. The problem is how to get smooth edges. So, "correct" detail value seems the only answer. At least with this code. Try my updated code above.

bee18

Pick detail value randomly, you'll get beautiful images out of the equation. Check out the latest update.

ccc

Happy Valentines Day!