Wrapping paper, anyone ?

simon pianomaestro at gmail.com
Wed Dec 16 00:46:26 EST 2009


#!/usr/bin/env python

from math import *

from random import *

import cairo
from cairo import Context

Black = (0, 0, 0)
White = (1, 1, 1)

def rand():
    return random()*2 - 1

def rotate(theta, x, y):
    x, y = x*cos(theta)-y*sin(theta), x*sin(theta)+y*cos(theta)
    return x, y

def star(ctx, n=5, r0=0.4):

    for c in range(2):
        ctx.set_source_rgba(*(White, Black)[c])
        x, y = 0, 1
        ctx.move_to(x, y)
        theta = 2*pi / n
        for i in range(n):
            x1, y1 = rotate(theta/2, x, y)
            ctx.line_to(r0*x1, r0*y1)
            x, y = rotate(theta/2, x1, y1)
            ctx.line_to(x, y)
        ctx.close_path()
        (ctx.fill, ctx.stroke)[c]()


class ScribeCall(object):
    def __init__(self, scribe, name):
        self.scribe = scribe
        self.name = name

    def __call__(self, *args, **kw):
        self.args = args
        self.kw = kw
        self.scribe.calls.append(self)


class Scribe(object):
    def __init__(self):
        self.calls = []

    __getattr__ = ScribeCall
    def run(self, ctx):
        for call in self.calls:
            #print "ctx.%s(%s)" % (call.name, ', '.join(str(x) for x
in call.args))
            getattr(ctx, call.name)(*call.args, **call.kw)


def orbit(dx, dy, w, h):
    x = -2*w
    while x < 2*w:
        y = -2*h
        while y < 2*h:
            yield x, y
            y += dy
        x += dx


def main_stars(w=800, h=1000):

    seed(0)

    surface = cairo.PSSurface('stars.ps', w, h)
    ctx = Context(surface)

    ctx.set_source_rgba(*White)
    ctx.rectangle(0, 0, w, h)
    ctx.fill()

    ctx.set_line_width(1./30)

    scribe = Scribe()

    for i in range(10):
        scribe.save()

        scribe.translate(w*random(), h*random())
        scribe.scale(20, 20)
        scribe.rotate(random() * 2 * pi)

        r = exp(random())
        scribe.scale(r, r)
        star(scribe, 5)
        scribe.scale(1./r, 1./r)

        scribe.translate(rand(), rand())
        scribe.restore()

    for x, y in orbit(120, 240, w, h):
        ctx.save()
        ctx.translate(x, y)
        scribe.run(ctx)
        ctx.restore()


if __name__=="__main__":
    main_stars()




More information about the Python-list mailing list